From 57c498fa5df05e4bd410c101795368439fec7b4e Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 20 Apr 2012 12:31:45 -0700 Subject: alarmtimer: Provide accessor to alarmtimer rtc device The Android alarm interface provides a settime call that sets both the alarmtimer RTC device and CLOCK_REALTIME to the same value. Since there may be multiple rtc devices, provide a hook to access the one the alarmtimer infrastructure is using. CC: Colin Cross CC: Thomas Gleixner CC: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- include/linux/alarmtimer.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index 975009e1cbe6..96c5c249b086 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h @@ -76,4 +76,7 @@ static inline int alarmtimer_callback_running(struct alarm *timer) } +/* Provide way to access the rtc device being used by alarmtimers */ +struct rtc_device *alarmtimer_get_rtcdev(void); + #endif -- cgit v1.2.3-71-gd317 From 06458e277eac2b8761b0a04d3c808d57be281a2e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 25 Apr 2012 15:54:58 +0100 Subject: IIO: Move core headers to include/linux/iio Step 1 in moving the IIO core out of staging. Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- .../staging/iio/Documentation/iio_event_monitor.c | 2 +- drivers/staging/iio/accel/adis16201_core.c | 6 +- drivers/staging/iio/accel/adis16201_ring.c | 4 +- drivers/staging/iio/accel/adis16201_trigger.c | 4 +- drivers/staging/iio/accel/adis16203_core.c | 6 +- drivers/staging/iio/accel/adis16203_ring.c | 4 +- drivers/staging/iio/accel/adis16203_trigger.c | 4 +- drivers/staging/iio/accel/adis16204_core.c | 6 +- drivers/staging/iio/accel/adis16204_ring.c | 4 +- drivers/staging/iio/accel/adis16204_trigger.c | 4 +- drivers/staging/iio/accel/adis16209_core.c | 6 +- drivers/staging/iio/accel/adis16209_ring.c | 4 +- drivers/staging/iio/accel/adis16209_trigger.c | 4 +- drivers/staging/iio/accel/adis16220_core.c | 4 +- drivers/staging/iio/accel/adis16240_core.c | 6 +- drivers/staging/iio/accel/adis16240_ring.c | 4 +- drivers/staging/iio/accel/adis16240_trigger.c | 4 +- drivers/staging/iio/accel/kxsd9.c | 4 +- drivers/staging/iio/accel/lis3l02dq_core.c | 8 +- drivers/staging/iio/accel/lis3l02dq_ring.c | 8 +- drivers/staging/iio/accel/sca3000_core.c | 8 +- drivers/staging/iio/accel/sca3000_ring.c | 6 +- drivers/staging/iio/adc/ad7192.c | 10 +- drivers/staging/iio/adc/ad7280a.c | 6 +- drivers/staging/iio/adc/ad7291.c | 6 +- drivers/staging/iio/adc/ad7298_core.c | 6 +- drivers/staging/iio/adc/ad7298_ring.c | 6 +- drivers/staging/iio/adc/ad7476_core.c | 6 +- drivers/staging/iio/adc/ad7476_ring.c | 6 +- drivers/staging/iio/adc/ad7606_core.c | 6 +- drivers/staging/iio/adc/ad7606_par.c | 2 +- drivers/staging/iio/adc/ad7606_ring.c | 6 +- drivers/staging/iio/adc/ad7606_spi.c | 2 +- drivers/staging/iio/adc/ad7780.c | 4 +- drivers/staging/iio/adc/ad7793.c | 10 +- drivers/staging/iio/adc/ad7816.c | 6 +- drivers/staging/iio/adc/ad7887_core.c | 6 +- drivers/staging/iio/adc/ad7887_ring.c | 6 +- drivers/staging/iio/adc/ad799x_core.c | 8 +- drivers/staging/iio/adc/ad799x_ring.c | 6 +- drivers/staging/iio/adc/adt7310.c | 6 +- drivers/staging/iio/adc/adt7410.c | 6 +- drivers/staging/iio/adc/lpc32xx_adc.c | 4 +- drivers/staging/iio/adc/max1363_core.c | 10 +- drivers/staging/iio/adc/max1363_ring.c | 6 +- drivers/staging/iio/adc/spear_adc.c | 4 +- drivers/staging/iio/addac/adt7316.c | 6 +- drivers/staging/iio/buffer.h | 191 --------- drivers/staging/iio/cdc/ad7150.c | 6 +- drivers/staging/iio/cdc/ad7152.c | 4 +- drivers/staging/iio/cdc/ad7746.c | 4 +- drivers/staging/iio/consumer.h | 96 ----- drivers/staging/iio/dac/ad5064.c | 4 +- drivers/staging/iio/dac/ad5360.c | 4 +- drivers/staging/iio/dac/ad5380.c | 4 +- drivers/staging/iio/dac/ad5421.c | 6 +- drivers/staging/iio/dac/ad5446.c | 4 +- drivers/staging/iio/dac/ad5504.c | 6 +- drivers/staging/iio/dac/ad5624r_spi.c | 4 +- drivers/staging/iio/dac/ad5686.c | 4 +- drivers/staging/iio/dac/ad5764.c | 4 +- drivers/staging/iio/dac/ad5791.c | 4 +- drivers/staging/iio/dac/max517.c | 4 +- drivers/staging/iio/dds/ad5930.c | 4 +- drivers/staging/iio/dds/ad9832.c | 4 +- drivers/staging/iio/dds/ad9834.c | 4 +- drivers/staging/iio/dds/ad9850.c | 4 +- drivers/staging/iio/dds/ad9852.c | 4 +- drivers/staging/iio/dds/ad9910.c | 4 +- drivers/staging/iio/dds/ad9951.c | 4 +- drivers/staging/iio/driver.h | 34 -- drivers/staging/iio/events.h | 105 ----- drivers/staging/iio/gyro/adis16060_core.c | 4 +- drivers/staging/iio/gyro/adis16080_core.c | 4 +- drivers/staging/iio/gyro/adis16130_core.c | 4 +- drivers/staging/iio/gyro/adis16260_core.c | 6 +- drivers/staging/iio/gyro/adis16260_ring.c | 4 +- drivers/staging/iio/gyro/adis16260_trigger.c | 4 +- drivers/staging/iio/gyro/adxrs450_core.c | 4 +- drivers/staging/iio/iio.h | 463 --------------------- drivers/staging/iio/iio_dummy_evgen.c | 4 +- drivers/staging/iio/iio_hwmon.c | 4 +- drivers/staging/iio/iio_simple_dummy.c | 8 +- drivers/staging/iio/iio_simple_dummy_buffer.c | 6 +- drivers/staging/iio/iio_simple_dummy_events.c | 6 +- drivers/staging/iio/impedance-analyzer/ad5933.c | 6 +- drivers/staging/iio/imu/adis16400_core.c | 6 +- drivers/staging/iio/imu/adis16400_ring.c | 4 +- drivers/staging/iio/imu/adis16400_trigger.c | 4 +- drivers/staging/iio/industrialio-buffer.c | 6 +- drivers/staging/iio/industrialio-core.c | 6 +- drivers/staging/iio/industrialio-event.c | 6 +- drivers/staging/iio/industrialio-trigger.c | 6 +- drivers/staging/iio/inkern.c | 8 +- drivers/staging/iio/kfifo_buf.c | 3 +- drivers/staging/iio/kfifo_buf.h | 8 - drivers/staging/iio/light/isl29018.c | 4 +- drivers/staging/iio/light/isl29028.c | 4 +- drivers/staging/iio/light/tsl2563.c | 6 +- drivers/staging/iio/light/tsl2583.c | 2 +- drivers/staging/iio/light/tsl2x7x_core.c | 6 +- drivers/staging/iio/machine.h | 24 -- drivers/staging/iio/magnetometer/ak8975.c | 4 +- drivers/staging/iio/magnetometer/hmc5843.c | 4 +- drivers/staging/iio/meter/ade7753.c | 4 +- drivers/staging/iio/meter/ade7754.c | 4 +- drivers/staging/iio/meter/ade7758_core.c | 6 +- drivers/staging/iio/meter/ade7758_ring.c | 4 +- drivers/staging/iio/meter/ade7758_trigger.c | 4 +- drivers/staging/iio/meter/ade7759.c | 4 +- drivers/staging/iio/meter/ade7854-i2c.c | 2 +- drivers/staging/iio/meter/ade7854-spi.c | 2 +- drivers/staging/iio/meter/ade7854.c | 4 +- drivers/staging/iio/meter/meter.h | 2 +- drivers/staging/iio/resolver/ad2s1200.c | 4 +- drivers/staging/iio/resolver/ad2s1210.c | 4 +- drivers/staging/iio/resolver/ad2s90.c | 4 +- drivers/staging/iio/ring_sw.c | 2 +- drivers/staging/iio/ring_sw.h | 2 +- drivers/staging/iio/sysfs.h | 117 ------ drivers/staging/iio/trigger.h | 119 ------ drivers/staging/iio/trigger/iio-trig-bfin-timer.c | 4 +- drivers/staging/iio/trigger/iio-trig-gpio.c | 4 +- .../staging/iio/trigger/iio-trig-periodic-rtc.c | 4 +- drivers/staging/iio/trigger/iio-trig-sysfs.c | 4 +- drivers/staging/iio/trigger_consumer.h | 52 --- drivers/staging/iio/types.h | 53 --- include/linux/iio/buffer.h | 191 +++++++++ include/linux/iio/consumer.h | 96 +++++ include/linux/iio/driver.h | 34 ++ include/linux/iio/events.h | 105 +++++ include/linux/iio/iio.h | 463 +++++++++++++++++++++ include/linux/iio/kfifo_buf.h | 8 + include/linux/iio/machine.h | 24 ++ include/linux/iio/sysfs.h | 117 ++++++ include/linux/iio/trigger.h | 119 ++++++ include/linux/iio/trigger_consumer.h | 52 +++ include/linux/iio/types.h | 53 +++ 138 files changed, 1542 insertions(+), 1543 deletions(-) delete mode 100644 drivers/staging/iio/buffer.h delete mode 100644 drivers/staging/iio/consumer.h delete mode 100644 drivers/staging/iio/driver.h delete mode 100644 drivers/staging/iio/events.h delete mode 100644 drivers/staging/iio/iio.h delete mode 100644 drivers/staging/iio/kfifo_buf.h delete mode 100644 drivers/staging/iio/machine.h delete mode 100644 drivers/staging/iio/sysfs.h delete mode 100644 drivers/staging/iio/trigger.h delete mode 100644 drivers/staging/iio/trigger_consumer.h delete mode 100644 drivers/staging/iio/types.h create mode 100644 include/linux/iio/buffer.h create mode 100644 include/linux/iio/consumer.h create mode 100644 include/linux/iio/driver.h create mode 100644 include/linux/iio/events.h create mode 100644 include/linux/iio/iio.h create mode 100644 include/linux/iio/kfifo_buf.h create mode 100644 include/linux/iio/machine.h create mode 100644 include/linux/iio/sysfs.h create mode 100644 include/linux/iio/trigger.h create mode 100644 include/linux/iio/trigger_consumer.h create mode 100644 include/linux/iio/types.h (limited to 'include/linux') diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 0d21a277305f..22275845fb12 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -27,7 +27,7 @@ #include #include #include "iio_utils.h" -#include "../events.h" +#include static const char * const iio_chan_type_name_spec[] = { [IIO_VOLTAGE] = "voltage", diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 8022bbdd4b63..9dce7b8d38a5 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -15,9 +15,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "adis16201.h" diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c index 49912e2dde3e..247602a8e54c 100644 --- a/drivers/staging/iio/accel/adis16201_ring.c +++ b/drivers/staging/iio/accel/adis16201_ring.c @@ -5,9 +5,9 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "adis16201.h" diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c index bce505e716d0..da687e01cc45 100644 --- a/drivers/staging/iio/accel/adis16201_trigger.c +++ b/drivers/staging/iio/accel/adis16201_trigger.c @@ -3,8 +3,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include #include "adis16201.h" /** diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index f23b7c5125af..cf1a0e565673 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -15,9 +15,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "adis16203.h" diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c index 5c40f6c72971..2171f7483e71 100644 --- a/drivers/staging/iio/accel/adis16203_ring.c +++ b/drivers/staging/iio/accel/adis16203_ring.c @@ -5,9 +5,9 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "adis16203.h" /** diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c index 24bcb8e15c55..1e1b981e1581 100644 --- a/drivers/staging/iio/accel/adis16203_trigger.c +++ b/drivers/staging/iio/accel/adis16203_trigger.c @@ -3,8 +3,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include #include "adis16203.h" /** diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index bffbbe8f737c..2a15d71c02c7 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -18,9 +18,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "adis16204.h" diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c index bf5488ecc65b..0a8b1255fd1c 100644 --- a/drivers/staging/iio/accel/adis16204_ring.c +++ b/drivers/staging/iio/accel/adis16204_ring.c @@ -5,9 +5,9 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "adis16204.h" /** diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c index 6e542af02c09..e6f2937ade7c 100644 --- a/drivers/staging/iio/accel/adis16204_trigger.c +++ b/drivers/staging/iio/accel/adis16204_trigger.c @@ -3,8 +3,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include #include "adis16204.h" /** diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index b1fbf19a71f3..cad411340f1d 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -16,9 +16,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "adis16209.h" diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c index 3101c537d13d..f7ed989dd20c 100644 --- a/drivers/staging/iio/accel/adis16209_ring.c +++ b/drivers/staging/iio/accel/adis16209_ring.c @@ -5,9 +5,9 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "adis16209.h" /** diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c index c5d82c1a55d9..5f5dbed447d7 100644 --- a/drivers/staging/iio/accel/adis16209_trigger.c +++ b/drivers/staging/iio/accel/adis16209_trigger.c @@ -3,8 +3,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include #include "adis16209.h" /** diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 2740c8e1398c..c86a3db6d747 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -15,8 +15,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "adis16220.h" diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 18ed39692b4d..fcc2c19f69dd 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -19,9 +19,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "adis16240.h" diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c index c4459f73e747..1aa95662e542 100644 --- a/drivers/staging/iio/accel/adis16240_ring.c +++ b/drivers/staging/iio/accel/adis16240_ring.c @@ -5,9 +5,9 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "adis16240.h" /** diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c index 8e0ce568e64c..53eda35b37e7 100644 --- a/drivers/staging/iio/accel/adis16240_trigger.c +++ b/drivers/staging/iio/accel/adis16240_trigger.c @@ -3,8 +3,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include #include "adis16240.h" /** diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c index 601da28f3b3a..329239011d47 100644 --- a/drivers/staging/iio/accel/kxsd9.c +++ b/drivers/staging/iio/accel/kxsd9.c @@ -23,8 +23,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define KXSD9_REG_X 0x00 #define KXSD9_REG_Y 0x02 diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index ee8ad3a3f981..bbef0be3d81e 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -23,10 +23,10 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "../buffer.h" +#include +#include +#include +#include #include "lis3l02dq.h" diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index ebd5b4d3d957..c8b8164eef77 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -6,11 +6,11 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../kfifo_buf.h" -#include "../trigger.h" -#include "../trigger_consumer.h" +#include +#include +#include #include "lis3l02dq.h" /** diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 646e05ccfa86..2ee5eb060932 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -18,10 +18,10 @@ #include #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "../buffer.h" +#include +#include +#include +#include #include "sca3000.h" diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 6b824a11f7f4..889bc86047f9 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -18,9 +18,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "../ring_hw.h" #include "sca3000.h" diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 5d316857c13a..14f983450d7f 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -17,12 +17,12 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "../ring_sw.h" -#include "../trigger.h" -#include "../trigger_consumer.h" +#include +#include #include "ad7192.h" diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index f0c0c72a1b07..d72780f91031 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -16,9 +16,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include #include "ad7280a.h" diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 298249f39887..b8e4fe6c0c50 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -17,9 +17,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include /* * Simplified handling diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c index 5d54a795a389..974a8e3ef26a 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -16,9 +16,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "ad7298.h" diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index 538e3b357e44..943caa340bfa 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -11,10 +11,10 @@ #include #include -#include "../iio.h" -#include "../buffer.h" +#include +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "ad7298.h" diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index ce715225eff3..1241b9fadbf7 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -15,9 +15,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "ad7476.h" diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c index 8534f6b3cccb..51403892bc8b 100644 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ b/drivers/staging/iio/adc/ad7476_ring.c @@ -13,10 +13,10 @@ #include #include -#include "../iio.h" -#include "../buffer.h" +#include +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "ad7476.h" diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 802cdaf538f2..9c540643576b 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -18,9 +18,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "ad7606.h" diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index bb152a8e8c92..a53faafec070 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -12,7 +12,7 @@ #include #include -#include "../iio.h" +#include #include "ad7606.h" static int ad7606_par16_read_block(struct device *dev, diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index 007b6005beed..3dd9602b1070 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -11,10 +11,10 @@ #include #include -#include "../iio.h" -#include "../buffer.h" +#include +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "ad7606.h" diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index 237f1c44d296..099d347da52d 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -11,7 +11,7 @@ #include #include -#include "../iio.h" +#include #include "ad7606.h" #define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index eeedbdb05a95..a8e661e5e4e6 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -18,8 +18,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "ad7780.h" diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 7f68c7c84ac6..3a7d1a7b4e05 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -18,12 +18,12 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "../ring_sw.h" -#include "../trigger.h" -#include "../trigger_consumer.h" +#include +#include #include "ad7793.h" diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 52b720e2b03a..586f6c2425e2 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -16,9 +16,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include /* * AD7816 config masks diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index 2cce09f36b74..fef916998f24 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -15,9 +15,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "ad7887.h" diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index 62681a8d43c1..f1846dbf49a0 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -12,10 +12,10 @@ #include #include -#include "../iio.h" -#include "../buffer.h" +#include +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "ad7887.h" diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 429fb414f2ea..561ae17ec7cc 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -33,10 +33,10 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "../buffer.h" +#include +#include +#include +#include #include "ad799x.h" diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index 5190e506716f..18366b5038ce 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -16,10 +16,10 @@ #include #include -#include "../iio.h" -#include "../buffer.h" +#include +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "ad799x.h" diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c index caf57c1169b1..223aea5952df 100644 --- a/drivers/staging/iio/adc/adt7310.c +++ b/drivers/staging/iio/adc/adt7310.c @@ -15,9 +15,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include /* * ADT7310 registers definition */ diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index dff3e8ca2d78..dab4a5abff8a 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -15,9 +15,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include /* * ADT7410 registers definition diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c index d7f4fe42d17e..0ddd91712f44 100644 --- a/drivers/staging/iio/adc/lpc32xx_adc.c +++ b/drivers/staging/iio/adc/lpc32xx_adc.c @@ -32,8 +32,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include /* * LPC32XX registers definitions diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 1a7a0274751d..7ab871c8aab5 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -32,11 +32,11 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" -#include "../buffer.h" -#include "../driver.h" +#include +#include +#include +#include +#include #include "max1363.h" diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index 8372e9819b60..b30201300121 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -14,10 +14,10 @@ #include #include -#include "../iio.h" -#include "../buffer.h" +#include +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "max1363.h" diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c index 3ca5cc9814eb..2b4e1eb8eab1 100644 --- a/drivers/staging/iio/adc/spear_adc.c +++ b/drivers/staging/iio/adc/spear_adc.c @@ -19,8 +19,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include /* * SPEAR registers definitions diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index fd6a45444058..f469ab3cc7b9 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -19,9 +19,9 @@ #include #include -#include "../iio.h" -#include "../events.h" -#include "../sysfs.h" +#include +#include +#include #include "adt7316.h" /* diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h deleted file mode 100644 index 3d3ea9ed53de..000000000000 --- a/drivers/staging/iio/buffer.h +++ /dev/null @@ -1,191 +0,0 @@ -/* The industrial I/O core - generic buffer interfaces. - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#ifndef _IIO_BUFFER_GENERIC_H_ -#define _IIO_BUFFER_GENERIC_H_ -#include -#include "iio.h" - -#ifdef CONFIG_IIO_BUFFER - -struct iio_buffer; - -/** - * struct iio_buffer_access_funcs - access functions for buffers. - * @store_to: actually store stuff to the buffer - * @read_first_n: try to get a specified number of bytes (must exist) - * @request_update: if a parameter change has been marked, update underlying - * storage. - * @get_bytes_per_datum:get current bytes per datum - * @set_bytes_per_datum:set number of bytes per datum - * @get_length: get number of datums in buffer - * @set_length: set number of datums in buffer - * - * The purpose of this structure is to make the buffer element - * modular as event for a given driver, different usecases may require - * different buffer designs (space efficiency vs speed for example). - * - * It is worth noting that a given buffer implementation may only support a - * small proportion of these functions. The core code 'should' cope fine with - * any of them not existing. - **/ -struct iio_buffer_access_funcs { - int (*store_to)(struct iio_buffer *buffer, u8 *data, s64 timestamp); - int (*read_first_n)(struct iio_buffer *buffer, - size_t n, - char __user *buf); - - int (*request_update)(struct iio_buffer *buffer); - - int (*get_bytes_per_datum)(struct iio_buffer *buffer); - int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); - int (*get_length)(struct iio_buffer *buffer); - int (*set_length)(struct iio_buffer *buffer, int length); -}; - -/** - * struct iio_buffer - general buffer structure - * @length: [DEVICE] number of datums in buffer - * @bytes_per_datum: [DEVICE] size of individual datum including timestamp - * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode - * control method is used - * @scan_mask: [INTERN] bitmask used in masking scan mode elements - * @scan_timestamp: [INTERN] does the scan mode include a timestamp - * @access: [DRIVER] buffer access functions associated with the - * implementation. - * @scan_el_dev_attr_list:[INTERN] list of scan element related attributes. - * @scan_el_group: [DRIVER] attribute group for those attributes not - * created from the iio_chan_info array. - * @pollq: [INTERN] wait queue to allow for polling on the buffer. - * @stufftoread: [INTERN] flag to indicate new data. - * @demux_list: [INTERN] list of operations required to demux the scan. - * @demux_bounce: [INTERN] buffer for doing gather from incoming scan. - **/ -struct iio_buffer { - int length; - int bytes_per_datum; - struct attribute_group *scan_el_attrs; - long *scan_mask; - bool scan_timestamp; - const struct iio_buffer_access_funcs *access; - struct list_head scan_el_dev_attr_list; - struct attribute_group scan_el_group; - wait_queue_head_t pollq; - bool stufftoread; - const struct attribute_group *attrs; - struct list_head demux_list; - unsigned char *demux_bounce; -}; - -/** - * iio_buffer_init() - Initialize the buffer structure - * @buffer: buffer to be initialized - **/ -void iio_buffer_init(struct iio_buffer *buffer); - -/** - * __iio_update_buffer() - update common elements of buffers - * @buffer: buffer that is the event source - * @bytes_per_datum: size of individual datum including timestamp - * @length: number of datums in buffer - **/ -static inline void __iio_update_buffer(struct iio_buffer *buffer, - int bytes_per_datum, int length) -{ - buffer->bytes_per_datum = bytes_per_datum; - buffer->length = length; -} - -int iio_scan_mask_query(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit); - -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - **/ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit); - -/** - * iio_push_to_buffer() - push to a registered buffer. - * @buffer: IIO buffer structure for device - * @scan: Full scan. - * @timestamp: - */ -int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, - s64 timestamp); - -int iio_update_demux(struct iio_dev *indio_dev); - -/** - * iio_buffer_register() - register the buffer with IIO core - * @indio_dev: device with the buffer to be registered - **/ -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels); - -/** - * iio_buffer_unregister() - unregister the buffer from IIO core - * @indio_dev: the device with the buffer to be unregistered - **/ -void iio_buffer_unregister(struct iio_dev *indio_dev); - -/** - * iio_buffer_read_length() - attr func to get number of datums in the buffer - **/ -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf); -/** - * iio_buffer_write_length() - attr func to set number of datums in the buffer - **/ -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_store_enable() - attr to turn the buffer on - **/ -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_show_enable() - attr to see if the buffer is on - **/ -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf); -#define IIO_BUFFER_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ - iio_buffer_read_length, \ - iio_buffer_write_length) - -#define IIO_BUFFER_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ - iio_buffer_show_enable, \ - iio_buffer_store_enable) - -int iio_sw_buffer_preenable(struct iio_dev *indio_dev); - -#else /* CONFIG_IIO_BUFFER */ - -static inline int iio_buffer_register(struct iio_dev *indio_dev, - struct iio_chan_spec *channels, - int num_channels) -{ - return 0; -} - -static inline void iio_buffer_unregister(struct iio_dev *indio_dev) -{}; - -#endif /* CONFIG_IIO_BUFFER */ - -#endif /* _IIO_BUFFER_GENERIC_H_ */ diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 116e6c278437..c0ccbc524c6e 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -13,9 +13,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include /* * AD7150 registers definition */ diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index 1067ce58e07d..ea403596c958 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -15,8 +15,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include /* * TODO: Check compliance of calibbias with abi (units) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 750bf4b0385e..74a889a6d899 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "ad7746.h" diff --git a/drivers/staging/iio/consumer.h b/drivers/staging/iio/consumer.h deleted file mode 100644 index 36a060cd3a21..000000000000 --- a/drivers/staging/iio/consumer.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Industrial I/O in kernel consumer interface - * - * Copyright (c) 2011 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#ifndef _IIO_INKERN_CONSUMER_H_ -#define _IIO_INKERN_CONSUMER_H -#include "types.h" - -struct iio_dev; -struct iio_chan_spec; - -/** - * struct iio_channel - everything needed for a consumer to use a channel - * @indio_dev: Device on which the channel exists. - * @channel: Full description of the channel. - */ -struct iio_channel { - struct iio_dev *indio_dev; - const struct iio_chan_spec *channel; -}; - -/** - * iio_channel_get() - get description of all that is needed to access channel. - * @name: Unique name of the device as provided in the iio_map - * with which the desired provider to consumer mapping - * was registered. - * @consumer_channel: Unique name to identify the channel on the consumer - * side. This typically describes the channels use within - * the consumer. E.g. 'battery_voltage' - */ -struct iio_channel *iio_st_channel_get(const char *name, - const char *consumer_channel); - -/** - * iio_st_channel_release() - release channels obtained via iio_st_channel_get - * @chan: The channel to be released. - */ -void iio_st_channel_release(struct iio_channel *chan); - -/** - * iio_st_channel_get_all() - get all channels associated with a client - * @name: name of consumer device. - * - * Returns an array of iio_channel structures terminated with one with - * null iio_dev pointer. - * This function is used by fairly generic consumers to get all the - * channels registered as having this consumer. - */ -struct iio_channel *iio_st_channel_get_all(const char *name); - -/** - * iio_st_channel_release_all() - reverse iio_st_get_all - * @chan: Array of channels to be released. - */ -void iio_st_channel_release_all(struct iio_channel *chan); - -/** - * iio_st_read_channel_raw() - read from a given channel - * @channel: The channel being queried. - * @val: Value read back. - * - * Note raw reads from iio channels are in adc counts and hence - * scale will need to be applied if standard units required. - */ -int iio_st_read_channel_raw(struct iio_channel *chan, - int *val); - -/** - * iio_st_get_channel_type() - get the type of a channel - * @channel: The channel being queried. - * @type: The type of the channel. - * - * returns the enum iio_chan_type of the channel - */ -int iio_st_get_channel_type(struct iio_channel *channel, - enum iio_chan_type *type); - -/** - * iio_st_read_channel_scale() - read the scale value for a channel - * @channel: The channel being queried. - * @val: First part of value read back. - * @val2: Second part of value read back. - * - * Note returns a description of what is in val and val2, such - * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val - * + val2/1e6 - */ -int iio_st_read_channel_scale(struct iio_channel *chan, int *val, - int *val2); - -#endif diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 21893edbf009..c0fad4fd13fa 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" #define AD5064_MAX_DAC_CHANNELS 8 diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c index cb6160d84b7b..0978dd2891b9 100644 --- a/drivers/staging/iio/dac/ad5360.c +++ b/drivers/staging/iio/dac/ad5360.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" #define AD5360_CMD(x) ((x) << 22) diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c index 1d384f01658c..aa077e676dfe 100644 --- a/drivers/staging/iio/dac/ad5380.c +++ b/drivers/staging/iio/dac/ad5380.c @@ -18,8 +18,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/staging/iio/dac/ad5421.c index a8b5211ac95a..b1a893ce2c88 100644 --- a/drivers/staging/iio/dac/ad5421.c +++ b/drivers/staging/iio/dac/ad5421.c @@ -16,9 +16,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include #include "dac.h" #include "ad5421.h" diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index 00b138e56d24..62ad1d5df475 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -18,8 +18,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" #include "ad5446.h" diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 796691e544a2..18fc391e62d4 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -16,9 +16,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include #include "dac.h" #include "ad5504.h" diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c index 74eb889afab1..c7786c18b847 100644 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ b/drivers/staging/iio/dac/ad5624r_spi.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" #include "ad5624r.h" diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c index b8acd7e572a2..86c869134bd4 100644 --- a/drivers/staging/iio/dac/ad5686.c +++ b/drivers/staging/iio/dac/ad5686.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" #define AD5686_DAC_CHANNELS 4 diff --git a/drivers/staging/iio/dac/ad5764.c b/drivers/staging/iio/dac/ad5764.c index 1c9ff4fc488d..b01d7eedb95e 100644 --- a/drivers/staging/iio/dac/ad5764.c +++ b/drivers/staging/iio/dac/ad5764.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" #define AD5764_REG_SF_NOP 0x0 diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index cdb7b109d6f9..c013868dfcd5 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -17,8 +17,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" #include "ad5791.h" diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c index 41483c72cec1..373127cc83a8 100644 --- a/drivers/staging/iio/dac/max517.c +++ b/drivers/staging/iio/dac/max517.c @@ -25,8 +25,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dac.h" #include "max517.h" diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c index 9c32d1beae25..6df4d86be849 100644 --- a/drivers/staging/iio/dds/ad5930.c +++ b/drivers/staging/iio/dds/ad5930.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define DRV_NAME "ad5930" diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c index 2ccf25dd9289..57627ff45c3a 100644 --- a/drivers/staging/iio/dds/ad9832.c +++ b/drivers/staging/iio/dds/ad9832.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dds.h" #include "ad9832.h" diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c index 38a2de08626f..9b2c8795f894 100644 --- a/drivers/staging/iio/dds/ad9834.c +++ b/drivers/staging/iio/dds/ad9834.c @@ -19,8 +19,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "dds.h" #include "ad9834.h" diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c index f4f731bb2191..cc7a87d25a59 100644 --- a/drivers/staging/iio/dds/ad9850.c +++ b/drivers/staging/iio/dds/ad9850.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define DRV_NAME "ad9850" diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c index 554266c615a8..2f8df7bcb783 100644 --- a/drivers/staging/iio/dds/ad9852.c +++ b/drivers/staging/iio/dds/ad9852.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define DRV_NAME "ad9852" diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c index 3985766d6f87..e91efc5c0fca 100644 --- a/drivers/staging/iio/dds/ad9910.c +++ b/drivers/staging/iio/dds/ad9910.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define DRV_NAME "ad9910" diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c index 4d150048002a..ca1d3111b0bf 100644 --- a/drivers/staging/iio/dds/ad9951.c +++ b/drivers/staging/iio/dds/ad9951.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define DRV_NAME "ad9951" diff --git a/drivers/staging/iio/driver.h b/drivers/staging/iio/driver.h deleted file mode 100644 index a4f8b2e05af5..000000000000 --- a/drivers/staging/iio/driver.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Industrial I/O in kernel access map interface. - * - * Copyright (c) 2011 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#ifndef _IIO_INKERN_H_ -#define _IIO_INKERN_H_ - -struct iio_map; - -/** - * iio_map_array_register() - tell the core about inkernel consumers - * @indio_dev: provider device - * @map: array of mappings specifying association of channel with client - */ -int iio_map_array_register(struct iio_dev *indio_dev, - struct iio_map *map); - -/** - * iio_map_array_unregister() - tell the core to remove consumer mappings - * @indio_dev: provider device - * @map: array of mappings to remove. Note these must have same memory - * addresses as those originally added not just equal parameter - * values. - */ -int iio_map_array_unregister(struct iio_dev *indio_dev, - struct iio_map *map); - -#endif diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h deleted file mode 100644 index c25f0e3c92e9..000000000000 --- a/drivers/staging/iio/events.h +++ /dev/null @@ -1,105 +0,0 @@ -/* The industrial I/O - event passing to userspace - * - * Copyright (c) 2008-2011 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#ifndef _IIO_EVENTS_H_ -#define _IIO_EVENTS_H_ - -#include -#include -#include "types.h" - -/** - * struct iio_event_data - The actual event being pushed to userspace - * @id: event identifier - * @timestamp: best estimate of time of event occurrence (often from - * the interrupt handler) - */ -struct iio_event_data { - __u64 id; - __s64 timestamp; -}; - -#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int) - -enum iio_event_type { - IIO_EV_TYPE_THRESH, - IIO_EV_TYPE_MAG, - IIO_EV_TYPE_ROC, - IIO_EV_TYPE_THRESH_ADAPTIVE, - IIO_EV_TYPE_MAG_ADAPTIVE, -}; - -enum iio_event_direction { - IIO_EV_DIR_EITHER, - IIO_EV_DIR_RISING, - IIO_EV_DIR_FALLING, -}; - -/** - * IIO_EVENT_CODE() - create event identifier - * @chan_type: Type of the channel. Should be one of enum iio_chan_type. - * @diff: Whether the event is for an differential channel or not. - * @modifier: Modifier for the channel. Should be one of enum iio_modifier. - * @direction: Direction of the event. One of enum iio_event_direction. - * @type: Type of the event. Should be one enum iio_event_type. - * @chan: Channel number for non-differential channels. - * @chan1: First channel number for differential channels. - * @chan2: Second channel number for differential channels. - */ - -#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \ - type, chan, chan1, chan2) \ - (((u64)type << 56) | ((u64)diff << 55) | \ - ((u64)direction << 48) | ((u64)modifier << 40) | \ - ((u64)chan_type << 32) | (((u16)chan2) << 16) | ((u16)chan1) | \ - ((u16)chan)) - - -#define IIO_EV_DIR_MAX 4 -#define IIO_EV_BIT(type, direction) \ - (1 << (type*IIO_EV_DIR_MAX + direction)) - -/** - * IIO_MOD_EVENT_CODE() - create event identifier for modified channels - * @chan_type: Type of the channel. Should be one of enum iio_chan_type. - * @number: Channel number. - * @modifier: Modifier for the channel. Should be one of enum iio_modifier. - * @type: Type of the event. Should be one enum iio_event_type. - * @direction: Direction of the event. One of enum iio_event_direction. - */ - -#define IIO_MOD_EVENT_CODE(chan_type, number, modifier, \ - type, direction) \ - IIO_EVENT_CODE(chan_type, 0, modifier, direction, type, number, 0, 0) - -/** - * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels - * @chan_type: Type of the channel. Should be one of enum iio_chan_type. - * @number: Channel number. - * @type: Type of the event. Should be one enum iio_event_type. - * @direction: Direction of the event. One of enum iio_event_direction. - */ - -#define IIO_UNMOD_EVENT_CODE(chan_type, number, type, direction) \ - IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0) - -#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) - -#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) - -#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF) - -/* Event code number extraction depends on which type of event we have. - * Perhaps review this function in the future*/ -#define IIO_EVENT_CODE_EXTRACT_CHAN(mask) ((__s16)(mask & 0xFFFF)) -#define IIO_EVENT_CODE_EXTRACT_CHAN2(mask) ((__s16)(((mask) >> 16) & 0xFFFF)) - -#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) -#define IIO_EVENT_CODE_EXTRACT_DIFF(mask) (((mask) >> 55) & 0x1) - -#endif diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c index 2f841cb19238..08aaf2783895 100644 --- a/drivers/staging/iio/gyro/adis16060_core.c +++ b/drivers/staging/iio/gyro/adis16060_core.c @@ -15,8 +15,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define ADIS16060_GYRO 0x20 /* Measure Angular Rate (Gyro) */ #define ADIS16060_TEMP_OUT 0x10 /* Measure Temperature */ diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index 608b93d07484..7e3695ba628b 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c @@ -14,8 +14,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */ #define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */ diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c index 257bdf2bfb46..98aa1b92b9d4 100644 --- a/drivers/staging/iio/gyro/adis16130_core.c +++ b/drivers/staging/iio/gyro/adis16130_core.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define ADIS16130_CON 0x0 #define ADIS16130_CON_RD (1 << 6) diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index bb2301833495..15253beab9a0 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -18,9 +18,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "adis16260.h" diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c index 046f84d0eeca..25283376f2fc 100644 --- a/drivers/staging/iio/gyro/adis16260_ring.c +++ b/drivers/staging/iio/gyro/adis16260_ring.c @@ -5,9 +5,9 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "adis16260.h" /** diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c index 8299cd18d705..dc56f3263762 100644 --- a/drivers/staging/iio/gyro/adis16260_trigger.c +++ b/drivers/staging/iio/gyro/adis16260_trigger.c @@ -3,8 +3,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include #include "adis16260.h" /** diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 12935057836e..06a9e974f010 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -18,8 +18,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "adxrs450.h" diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h deleted file mode 100644 index 077034019c2f..000000000000 --- a/drivers/staging/iio/iio.h +++ /dev/null @@ -1,463 +0,0 @@ - -/* The industrial I/O core - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#ifndef _INDUSTRIAL_IO_H_ -#define _INDUSTRIAL_IO_H_ - -#include -#include -#include "types.h" -/* IIO TODO LIST */ -/* - * Provide means of adjusting timer accuracy. - * Currently assumes nano seconds. - */ - -enum iio_chan_info_enum { - IIO_CHAN_INFO_RAW = 0, - IIO_CHAN_INFO_PROCESSED, - IIO_CHAN_INFO_SCALE, - IIO_CHAN_INFO_OFFSET, - IIO_CHAN_INFO_CALIBSCALE, - IIO_CHAN_INFO_CALIBBIAS, - IIO_CHAN_INFO_PEAK, - IIO_CHAN_INFO_PEAK_SCALE, - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW, - IIO_CHAN_INFO_AVERAGE_RAW, - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY, - IIO_CHAN_INFO_SAMP_FREQ, -}; - -#define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) -#define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) - -#define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) -#define IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PROCESSED) -#define IIO_CHAN_INFO_SCALE_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SCALE) -#define IIO_CHAN_INFO_SCALE_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SCALE) -#define IIO_CHAN_INFO_OFFSET_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_OFFSET) -#define IIO_CHAN_INFO_OFFSET_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_OFFSET) -#define IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBSCALE) -#define IIO_CHAN_INFO_CALIBSCALE_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBSCALE) -#define IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBBIAS) -#define IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBBIAS) -#define IIO_CHAN_INFO_PEAK_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAK) -#define IIO_CHAN_INFO_PEAK_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAK) -#define IIO_CHAN_INFO_PEAKSCALE_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAKSCALE) -#define IIO_CHAN_INFO_PEAKSCALE_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAKSCALE) -#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT( \ - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) -#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT( \ - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) -#define IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_AVERAGE_RAW) -#define IIO_CHAN_INFO_AVERAGE_RAW_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_AVERAGE_RAW) -#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT( \ - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) -#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT( \ - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) -#define IIO_CHAN_INFO_SAMP_FREQ_SEPARATE_BIT \ - IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SAMP_FREQ) -#define IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT \ - IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SAMP_FREQ) - -enum iio_endian { - IIO_CPU, - IIO_BE, - IIO_LE, -}; - -struct iio_chan_spec; -struct iio_dev; - -/** - * struct iio_chan_spec_ext_info - Extended channel info attribute - * @name: Info attribute name - * @shared: Whether this attribute is shared between all channels. - * @read: Read callback for this info attribute, may be NULL. - * @write: Write callback for this info attribute, may be NULL. - */ -struct iio_chan_spec_ext_info { - const char *name; - bool shared; - ssize_t (*read)(struct iio_dev *, struct iio_chan_spec const *, - char *buf); - ssize_t (*write)(struct iio_dev *, struct iio_chan_spec const *, - const char *buf, size_t len); -}; - -/** - * struct iio_chan_spec - specification of a single channel - * @type: What type of measurement is the channel making. - * @channel: What number or name do we wish to assign the channel. - * @channel2: If there is a second number for a differential - * channel then this is it. If modified is set then the - * value here specifies the modifier. - * @address: Driver specific identifier. - * @scan_index: Monotonic index to give ordering in scans when read - * from a buffer. - * @scan_type: Sign: 's' or 'u' to specify signed or unsigned - * realbits: Number of valid bits of data - * storage_bits: Realbits + padding - * shift: Shift right by this before masking out - * realbits. - * endianness: little or big endian - * @info_mask: What information is to be exported about this channel. - * This includes calibbias, scale etc. - * @event_mask: What events can this channel produce. - * @ext_info: Array of extended info attributes for this channel. - * The array is NULL terminated, the last element should - * have it's name field set to NULL. - * @extend_name: Allows labeling of channel attributes with an - * informative name. Note this has no effect codes etc, - * unlike modifiers. - * @datasheet_name: A name used in in kernel mapping of channels. It should - * correspond to the first name that the channel is referred - * to by in the datasheet (e.g. IND), or the nearest - * possible compound name (e.g. IND-INC). - * @modified: Does a modifier apply to this channel. What these are - * depends on the channel type. Modifier is set in - * channel2. Examples are IIO_MOD_X for axial sensors about - * the 'x' axis. - * @indexed: Specify the channel has a numerical index. If not, - * the value in channel will be suppressed for attribute - * but not for event codes. Typically set it to 0 when - * the index is false. - * @differential: Channel is differential. - */ -struct iio_chan_spec { - enum iio_chan_type type; - int channel; - int channel2; - unsigned long address; - int scan_index; - struct { - char sign; - u8 realbits; - u8 storagebits; - u8 shift; - enum iio_endian endianness; - } scan_type; - long info_mask; - long event_mask; - const struct iio_chan_spec_ext_info *ext_info; - const char *extend_name; - const char *datasheet_name; - unsigned modified:1; - unsigned indexed:1; - unsigned output:1; - unsigned differential:1; -}; - -#define IIO_ST(si, rb, sb, sh) \ - { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } - -#define IIO_CHAN_SOFT_TIMESTAMP(_si) \ - { .type = IIO_TIMESTAMP, .channel = -1, \ - .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) } - -/** - * iio_get_time_ns() - utility function to get a time stamp for events etc - **/ -static inline s64 iio_get_time_ns(void) -{ - struct timespec ts; - /* - * calls getnstimeofday. - * If hrtimers then up to ns accurate, if not microsecond. - */ - ktime_get_real_ts(&ts); - - return timespec_to_ns(&ts); -} - -/* Device operating modes */ -#define INDIO_DIRECT_MODE 0x01 -#define INDIO_BUFFER_TRIGGERED 0x02 -#define INDIO_BUFFER_HARDWARE 0x08 - -#define INDIO_ALL_BUFFER_MODES \ - (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE) - -struct iio_trigger; /* forward declaration */ -struct iio_dev; - -/** - * struct iio_info - constant information about device - * @driver_module: module structure used to ensure correct - * ownership of chrdevs etc - * @event_attrs: event control attributes - * @attrs: general purpose device attributes - * @read_raw: function to request a value from the device. - * mask specifies which value. Note 0 means a reading of - * the channel in question. Return value will specify the - * type of value returned by the device. val and val2 will - * contain the elements making up the returned value. - * @write_raw: function to write a value to the device. - * Parameters are the same as for read_raw. - * @write_raw_get_fmt: callback function to query the expected - * format/precision. If not set by the driver, write_raw - * returns IIO_VAL_INT_PLUS_MICRO. - * @read_event_config: find out if the event is enabled. - * @write_event_config: set if the event is enabled. - * @read_event_value: read a value associated with the event. Meaning - * is event dependant. event_code specifies which event. - * @write_event_value: write the value associated with the event. - * Meaning is event dependent. - * @validate_trigger: function to validate the trigger when the - * current trigger gets changed. - **/ -struct iio_info { - struct module *driver_module; - struct attribute_group *event_attrs; - const struct attribute_group *attrs; - - int (*read_raw)(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask); - - int (*write_raw)(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask); - - int (*write_raw_get_fmt)(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask); - - int (*read_event_config)(struct iio_dev *indio_dev, - u64 event_code); - - int (*write_event_config)(struct iio_dev *indio_dev, - u64 event_code, - int state); - - int (*read_event_value)(struct iio_dev *indio_dev, - u64 event_code, - int *val); - int (*write_event_value)(struct iio_dev *indio_dev, - u64 event_code, - int val); - int (*validate_trigger)(struct iio_dev *indio_dev, - struct iio_trigger *trig); - int (*update_scan_mode)(struct iio_dev *indio_dev, - const unsigned long *scan_mask); - int (*debugfs_reg_access)(struct iio_dev *indio_dev, - unsigned reg, unsigned writeval, - unsigned *readval); -}; - -/** - * struct iio_buffer_setup_ops - buffer setup related callbacks - * @preenable: [DRIVER] function to run prior to marking buffer enabled - * @postenable: [DRIVER] function to run after marking buffer enabled - * @predisable: [DRIVER] function to run prior to marking buffer - * disabled - * @postdisable: [DRIVER] function to run after marking buffer disabled - */ -struct iio_buffer_setup_ops { - int (*preenable)(struct iio_dev *); - int (*postenable)(struct iio_dev *); - int (*predisable)(struct iio_dev *); - int (*postdisable)(struct iio_dev *); -}; - -/** - * struct iio_dev - industrial I/O device - * @id: [INTERN] used to identify device internally - * @modes: [DRIVER] operating modes supported by device - * @currentmode: [DRIVER] current operating mode - * @dev: [DRIVER] device structure, should be assigned a parent - * and owner - * @event_interface: [INTERN] event chrdevs associated with interrupt lines - * @buffer: [DRIVER] any buffer present - * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux - * @mlock: [INTERN] lock used to prevent simultaneous device state - * changes - * @available_scan_masks: [DRIVER] optional array of allowed bitmasks - * @masklength: [INTERN] the length of the mask established from - * channels - * @active_scan_mask: [INTERN] union of all scan masks requested by buffers - * @scan_timestamp: [INTERN] set if any buffers have requested timestamp - * @scan_index_timestamp:[INTERN] cache of the index to the timestamp - * @trig: [INTERN] current device trigger (buffer modes) - * @pollfunc: [DRIVER] function run on trigger being received - * @channels: [DRIVER] channel specification structure table - * @num_channels: [DRIVER] number of chanels specified in @channels. - * @channel_attr_list: [INTERN] keep track of automatically created channel - * attributes - * @chan_attr_group: [INTERN] group for all attrs in base directory - * @name: [DRIVER] name of the device. - * @info: [DRIVER] callbacks and constant info from driver - * @info_exist_lock: [INTERN] lock to prevent use during removal - * @setup_ops: [DRIVER] callbacks to call before and after buffer - * enable/disable - * @chrdev: [INTERN] associated character device - * @groups: [INTERN] attribute groups - * @groupcounter: [INTERN] index of next attribute group - * @flags: [INTERN] file ops related flags including busy flag. - * @debugfs_dentry: [INTERN] device specific debugfs dentry. - * @cached_reg_addr: [INTERN] cached register address for debugfs reads. - */ -struct iio_dev { - int id; - - int modes; - int currentmode; - struct device dev; - - struct iio_event_interface *event_interface; - - struct iio_buffer *buffer; - int scan_bytes; - struct mutex mlock; - - const unsigned long *available_scan_masks; - unsigned masklength; - const unsigned long *active_scan_mask; - bool scan_timestamp; - unsigned scan_index_timestamp; - struct iio_trigger *trig; - struct iio_poll_func *pollfunc; - - struct iio_chan_spec const *channels; - int num_channels; - - struct list_head channel_attr_list; - struct attribute_group chan_attr_group; - const char *name; - const struct iio_info *info; - struct mutex info_exist_lock; - const struct iio_buffer_setup_ops *setup_ops; - struct cdev chrdev; -#define IIO_MAX_GROUPS 6 - const struct attribute_group *groups[IIO_MAX_GROUPS + 1]; - int groupcounter; - - unsigned long flags; -#if defined(CONFIG_DEBUG_FS) - struct dentry *debugfs_dentry; - unsigned cached_reg_addr; -#endif -}; - -/** - * iio_find_channel_from_si() - get channel from its scan index - * @indio_dev: device - * @si: scan index to match - */ -const struct iio_chan_spec -*iio_find_channel_from_si(struct iio_dev *indio_dev, int si); - -/** - * iio_device_register() - register a device with the IIO subsystem - * @indio_dev: Device structure filled by the device driver - **/ -int iio_device_register(struct iio_dev *indio_dev); - -/** - * iio_device_unregister() - unregister a device from the IIO subsystem - * @indio_dev: Device structure representing the device. - **/ -void iio_device_unregister(struct iio_dev *indio_dev); - -/** - * iio_push_event() - try to add event to the list for userspace reading - * @indio_dev: IIO device structure - * @ev_code: What event - * @timestamp: When the event occurred - **/ -int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp); - -extern struct bus_type iio_bus_type; - -/** - * iio_put_device() - reference counted deallocation of struct device - * @dev: the iio_device containing the device - **/ -static inline void iio_put_device(struct iio_dev *indio_dev) -{ - if (indio_dev) - put_device(&indio_dev->dev); -}; - -/* Can we make this smaller? */ -#define IIO_ALIGN L1_CACHE_BYTES -/** - * iio_allocate_device() - allocate an iio_dev from a driver - * @sizeof_priv: Space to allocate for private structure. - **/ -struct iio_dev *iio_allocate_device(int sizeof_priv); - -static inline void *iio_priv(const struct iio_dev *indio_dev) -{ - return (char *)indio_dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN); -} - -static inline struct iio_dev *iio_priv_to_dev(void *priv) -{ - return (struct iio_dev *)((char *)priv - - ALIGN(sizeof(struct iio_dev), IIO_ALIGN)); -} - -/** - * iio_free_device() - free an iio_dev from a driver - * @dev: the iio_dev associated with the device - **/ -void iio_free_device(struct iio_dev *indio_dev); - -/** - * iio_buffer_enabled() - helper function to test if the buffer is enabled - * @indio_dev: IIO device info structure for device - **/ -static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) -{ - return indio_dev->currentmode - & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); -}; - -/** - * iio_get_debugfs_dentry() - helper function to get the debugfs_dentry - * @indio_dev: IIO device info structure for device - **/ -#if defined(CONFIG_DEBUG_FS) -static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) -{ - return indio_dev->debugfs_dentry; -}; -#else -static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) -{ - return NULL; -}; -#endif - -#endif /* _INDUSTRIAL_IO_H_ */ diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c index f39f346bf04f..0cd4fe916bf9 100644 --- a/drivers/staging/iio/iio_dummy_evgen.c +++ b/drivers/staging/iio/iio_dummy_evgen.c @@ -22,8 +22,8 @@ #include #include "iio_dummy_evgen.h" -#include "iio.h" -#include "sysfs.h" +#include +#include /* Fiddly bit of faking and irq without hardware */ #define IIO_EVENTGEN_NO 10 diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c index a603a5f51f93..b03554fee443 100644 --- a/drivers/staging/iio/iio_hwmon.c +++ b/drivers/staging/iio/iio_hwmon.c @@ -14,8 +14,8 @@ #include #include #include -#include "consumer.h" -#include "types.h" +#include +#include /** * struct iio_hwmon_state - device instance state diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index dbeb04c70f0f..fa4a65329009 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -19,10 +19,10 @@ #include #include -#include "iio.h" -#include "sysfs.h" -#include "events.h" -#include "buffer.h" +#include +#include +#include +#include #include "iio_simple_dummy.h" /* diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index 49e7aa19889f..372606572d15 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -18,9 +18,9 @@ #include #include -#include "iio.h" -#include "trigger_consumer.h" -#include "kfifo_buf.h" +#include +#include +#include #include "iio_simple_dummy.h" diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 449c7a5ece80..f85bd197ed31 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -12,9 +12,9 @@ #include #include -#include "iio.h" -#include "sysfs.h" -#include "events.h" +#include +#include +#include #include "iio_simple_dummy.h" /* Evgen 'fakes' interrupt events for this example */ diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 8a0485e69747..9d99a7f67fa4 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -19,9 +19,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "../ring_sw.h" #include "ad5933.h" diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 58a150c1e435..68ecc1525017 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -26,9 +26,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "adis16400.h" enum adis16400_chip_variant { diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index d964004fe11b..e43c0e2f43a6 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -6,9 +6,9 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "adis16400.h" /** diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c index 5bf000757522..bd22e6cc11c3 100644 --- a/drivers/staging/iio/imu/adis16400_trigger.c +++ b/drivers/staging/iio/imu/adis16400_trigger.c @@ -3,8 +3,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include #include "adis16400.h" /** diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c index b409b95b5ee5..b5b2c38045c5 100644 --- a/drivers/staging/iio/industrialio-buffer.c +++ b/drivers/staging/iio/industrialio-buffer.c @@ -21,10 +21,10 @@ #include #include -#include "iio.h" +#include #include "iio_core.h" -#include "sysfs.h" -#include "buffer.h" +#include +#include static const char * const iio_endian_prefix[] = { [IIO_BE] = "be", diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index db55b815a24e..dd1a6a2e81c0 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -23,11 +23,11 @@ #include #include #include -#include "iio.h" +#include #include "iio_core.h" #include "iio_core_trigger.h" -#include "sysfs.h" -#include "events.h" +#include +#include /* IDA to assign each registered device a unique id*/ static DEFINE_IDA(iio_ida); diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index 5fdf739e38f9..5fcf50b1ae5a 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -20,10 +20,10 @@ #include #include #include -#include "iio.h" +#include #include "iio_core.h" -#include "sysfs.h" -#include "events.h" +#include +#include /** * struct iio_event_interface - chrdev interface for an event line diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c index 47ecadd4818d..03fee2e097ca 100644 --- a/drivers/staging/iio/industrialio-trigger.c +++ b/drivers/staging/iio/industrialio-trigger.c @@ -15,11 +15,11 @@ #include #include -#include "iio.h" -#include "trigger.h" +#include +#include #include "iio_core.h" #include "iio_core_trigger.h" -#include "trigger_consumer.h" +#include /* RFC - Question of approach * Make the common case (single sensor single trigger) diff --git a/drivers/staging/iio/inkern.c b/drivers/staging/iio/inkern.c index de2c8ea64965..22ddf62b107c 100644 --- a/drivers/staging/iio/inkern.c +++ b/drivers/staging/iio/inkern.c @@ -11,11 +11,11 @@ #include #include -#include "iio.h" +#include #include "iio_core.h" -#include "machine.h" -#include "driver.h" -#include "consumer.h" +#include +#include +#include struct iio_map_internal { struct iio_dev *indio_dev; diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c index 9f3bd59c0e72..6bf9d05f4841 100644 --- a/drivers/staging/iio/kfifo_buf.c +++ b/drivers/staging/iio/kfifo_buf.c @@ -5,8 +5,7 @@ #include #include #include - -#include "kfifo_buf.h" +#include struct iio_kfifo { struct iio_buffer buffer; diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h deleted file mode 100644 index 9f7da016af04..000000000000 --- a/drivers/staging/iio/kfifo_buf.h +++ /dev/null @@ -1,8 +0,0 @@ - -#include -#include "iio.h" -#include "buffer.h" - -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); -void iio_kfifo_free(struct iio_buffer *r); - diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 2c894a6f7881..92283ebafa55 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -28,8 +28,8 @@ #include #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define CONVERSION_TIME_MS 100 diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 7057d9b56624..2ada20e65f22 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -24,8 +24,8 @@ #include #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define CONVERSION_TIME_MS 100 diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index a1e5cbeb25ac..635136004103 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -35,9 +35,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../events.h" +#include +#include +#include #include "tsl2563.h" /* Use this many bits for fraction part. */ diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 8671d98e0448..51b636241d97 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -28,7 +28,7 @@ #include #include #include -#include "../iio.h" +#include #define TSL258X_MAX_DEVICE_REGS 32 diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index f3fc85a22b1a..dfc3da6e92e9 100755 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -28,10 +28,10 @@ #include #include #include +#include +#include +#include #include "tsl2x7x.h" -#include "../events.h" -#include "../iio.h" -#include "../sysfs.h" /* Cal defs*/ #define PROX_STAT_CAL 0 diff --git a/drivers/staging/iio/machine.h b/drivers/staging/iio/machine.h deleted file mode 100644 index 0b1f19bfdc44..000000000000 --- a/drivers/staging/iio/machine.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Industrial I/O in kernel access map definitions for board files. - * - * Copyright (c) 2011 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -/** - * struct iio_map - description of link between consumer and device channels - * @adc_channel_label: Label used to identify the channel on the provider. - * This is matched against the datasheet_name element - * of struct iio_chan_spec. - * @consumer_dev_name: Name to uniquely identify the consumer device. - * @consumer_channel: Unique name used to idenitify the channel on the - * consumer side. - */ -struct iio_map { - const char *adc_channel_label; - const char *consumer_dev_name; - const char *consumer_channel; -}; diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 000886fb81a9..d088548c2fa8 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -30,8 +30,8 @@ #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include /* * Register definitions, as well as various shifts and masks to get at the * individual fields of the registers. diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 27c26294b261..3433c41fe548 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -22,8 +22,8 @@ #include #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define HMC5843_I2C_ADDRESS 0x1E diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 57baac6c0d40..9b26ae1f23b7 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -18,8 +18,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "meter.h" #include "ade7753.h" diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index 8d81c92007e9..02d10dfe8ac5 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -18,8 +18,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "meter.h" #include "ade7754.h" diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 729c03311b9e..4a3b429003f1 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -18,9 +18,9 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" -#include "../buffer.h" +#include +#include +#include #include "meter.h" #include "ade7758.h" diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index b37bc98ce4d7..7b9be8a2cc50 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -12,9 +12,9 @@ #include #include -#include "../iio.h" +#include #include "../ring_sw.h" -#include "../trigger_consumer.h" +#include #include "ade7758.h" /** diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c index b6569c706651..5c48d382dfdb 100644 --- a/drivers/staging/iio/meter/ade7758_trigger.c +++ b/drivers/staging/iio/meter/ade7758_trigger.c @@ -11,8 +11,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include #include "ade7758.h" /** diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 0beab478dcd9..1f2b74add572 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -18,8 +18,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "meter.h" #include "ade7759.h" diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c index 1e1faa0479d3..c87c86b095e0 100644 --- a/drivers/staging/iio/meter/ade7854-i2c.c +++ b/drivers/staging/iio/meter/ade7854-i2c.c @@ -12,7 +12,7 @@ #include #include -#include "../iio.h" +#include #include "ade7854.h" static int ade7854_i2c_write_reg_8(struct device *dev, diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c index 81121862c1bd..11c2cef0e73b 100644 --- a/drivers/staging/iio/meter/ade7854-spi.c +++ b/drivers/staging/iio/meter/ade7854-spi.c @@ -12,7 +12,7 @@ #include #include -#include "../iio.h" +#include #include "ade7854.h" static int ade7854_spi_write_reg_8(struct device *dev, diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index 49c01c5c1b59..2f3c1e2a4b14 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -17,8 +17,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "meter.h" #include "ade7854.h" diff --git a/drivers/staging/iio/meter/meter.h b/drivers/staging/iio/meter/meter.h index 6a3db1423631..23e1b5f480a9 100644 --- a/drivers/staging/iio/meter/meter.h +++ b/drivers/staging/iio/meter/meter.h @@ -1,4 +1,4 @@ -#include "../sysfs.h" +#include /* metering ic types of attribute */ diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index 0465e5dff23a..48e70e9effd5 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -19,8 +19,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #define DRV_NAME "ad2s1200" diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index c6ced163105d..4d580e238eb8 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -18,8 +18,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include #include "ad2s1210.h" #define DRV_NAME "ad2s1210" diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c index 20ca5298cdf2..cb689104937f 100644 --- a/drivers/staging/iio/resolver/ad2s90.c +++ b/drivers/staging/iio/resolver/ad2s90.c @@ -16,8 +16,8 @@ #include #include -#include "../iio.h" -#include "../sysfs.h" +#include +#include struct ad2s90_state { struct mutex lock; diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index b9945ec44faa..9358c6cb1c72 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -15,7 +15,7 @@ #include #include #include "ring_sw.h" -#include "trigger.h" +#include /** * struct iio_sw_ring_buffer - software ring buffer diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h index 7556e2122367..a5857aa7aefa 100644 --- a/drivers/staging/iio/ring_sw.h +++ b/drivers/staging/iio/ring_sw.h @@ -23,7 +23,7 @@ #ifndef _IIO_RING_SW_H_ #define _IIO_RING_SW_H_ -#include "buffer.h" +#include struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev); void iio_sw_rb_free(struct iio_buffer *ring); diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h deleted file mode 100644 index bfedb73b850e..000000000000 --- a/drivers/staging/iio/sysfs.h +++ /dev/null @@ -1,117 +0,0 @@ -/* The industrial I/O core - * - *Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * General attributes - */ - -#ifndef _INDUSTRIAL_IO_SYSFS_H_ -#define _INDUSTRIAL_IO_SYSFS_H_ - -struct iio_chan_spec; - -/** - * struct iio_dev_attr - iio specific device attribute - * @dev_attr: underlying device attribute - * @address: associated register address - * @l: list head for maintaining list of dynamically created attrs. - */ -struct iio_dev_attr { - struct device_attribute dev_attr; - u64 address; - struct list_head l; - struct iio_chan_spec const *c; -}; - -#define to_iio_dev_attr(_dev_attr) \ - container_of(_dev_attr, struct iio_dev_attr, dev_attr) - -ssize_t iio_read_const_attr(struct device *dev, - struct device_attribute *attr, - char *len); - -/** - * struct iio_const_attr - constant device specific attribute - * often used for things like available modes - * @string: attribute string - * @dev_attr: underlying device attribute - */ -struct iio_const_attr { - const char *string; - struct device_attribute dev_attr; -}; - -#define to_iio_const_attr(_dev_attr) \ - container_of(_dev_attr, struct iio_const_attr, dev_attr) - -/* Some attributes will be hard coded (device dependent) and not require an - address, in these cases pass a negative */ -#define IIO_ATTR(_name, _mode, _show, _store, _addr) \ - { .dev_attr = __ATTR(_name, _mode, _show, _store), \ - .address = _addr } - -#define IIO_DEVICE_ATTR(_name, _mode, _show, _store, _addr) \ - struct iio_dev_attr iio_dev_attr_##_name \ - = IIO_ATTR(_name, _mode, _show, _store, _addr) - -#define IIO_DEVICE_ATTR_NAMED(_vname, _name, _mode, _show, _store, _addr) \ - struct iio_dev_attr iio_dev_attr_##_vname \ - = IIO_ATTR(_name, _mode, _show, _store, _addr) - -#define IIO_CONST_ATTR(_name, _string) \ - struct iio_const_attr iio_const_attr_##_name \ - = { .string = _string, \ - .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} - -#define IIO_CONST_ATTR_NAMED(_vname, _name, _string) \ - struct iio_const_attr iio_const_attr_##_vname \ - = { .string = _string, \ - .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} - -/* Generic attributes of onetype or another */ -/** - * IIO_DEV_ATTR_RESET: resets the device - **/ -#define IIO_DEV_ATTR_RESET(_store) \ - IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0) - -/** - * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency - * @_mode: sysfs file mode/permissions - * @_show: output method for the attribute - * @_store: input method for the attribute - **/ -#define IIO_DEV_ATTR_SAMP_FREQ(_mode, _show, _store) \ - IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) - -/** - * IIO_DEV_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies - * @_show: output method for the attribute - * - * May be mode dependent on some devices - **/ -#define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show) \ - IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0) -/** - * IIO_CONST_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies - * @_string: frequency string for the attribute - * - * Constant version - **/ -#define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \ - IIO_CONST_ATTR(sampling_frequency_available, _string) - -#define IIO_DEV_ATTR_TEMP_RAW(_show) \ - IIO_DEVICE_ATTR(in_temp_raw, S_IRUGO, _show, NULL, 0) - -#define IIO_CONST_ATTR_TEMP_OFFSET(_string) \ - IIO_CONST_ATTR(in_temp_offset, _string) - -#define IIO_CONST_ATTR_TEMP_SCALE(_string) \ - IIO_CONST_ATTR(in_temp_scale, _string) - -#endif /* _INDUSTRIAL_IO_SYSFS_H_ */ diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h deleted file mode 100644 index 1cfca231db8f..000000000000 --- a/drivers/staging/iio/trigger.h +++ /dev/null @@ -1,119 +0,0 @@ -/* The industrial I/O core, trigger handling functions - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#include -#include - -#ifndef _IIO_TRIGGER_H_ -#define _IIO_TRIGGER_H_ - -struct iio_subirq { - bool enabled; -}; - -/** - * struct iio_trigger_ops - operations structure for an iio_trigger. - * @owner: used to monitor usage count of the trigger. - * @set_trigger_state: switch on/off the trigger on demand - * @try_reenable: function to reenable the trigger when the - * use count is zero (may be NULL) - * @validate_device: function to validate the device when the - * current trigger gets changed. - * - * This is typically static const within a driver and shared by - * instances of a given device. - **/ -struct iio_trigger_ops { - struct module *owner; - int (*set_trigger_state)(struct iio_trigger *trig, bool state); - int (*try_reenable)(struct iio_trigger *trig); - int (*validate_device)(struct iio_trigger *trig, - struct iio_dev *indio_dev); -}; - - -/** - * struct iio_trigger - industrial I/O trigger device - * - * @id: [INTERN] unique id number - * @name: [DRIVER] unique name - * @dev: [DRIVER] associated device (if relevant) - * @private_data: [DRIVER] device specific data - * @list: [INTERN] used in maintenance of global trigger list - * @alloc_list: [DRIVER] used for driver specific trigger list - * @use_count: use count for the trigger - * @subirq_chip: [INTERN] associate 'virtual' irq chip. - * @subirq_base: [INTERN] base number for irqs provided by trigger. - * @subirqs: [INTERN] information about the 'child' irqs. - * @pool: [INTERN] bitmap of irqs currently in use. - * @pool_lock: [INTERN] protection of the irq pool. - **/ -struct iio_trigger { - const struct iio_trigger_ops *ops; - int id; - const char *name; - struct device dev; - - void *private_data; - struct list_head list; - struct list_head alloc_list; - int use_count; - - struct irq_chip subirq_chip; - int subirq_base; - - struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER]; - unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; - struct mutex pool_lock; -}; - - -static inline struct iio_trigger *to_iio_trigger(struct device *d) -{ - return container_of(d, struct iio_trigger, dev); -}; - -static inline void iio_put_trigger(struct iio_trigger *trig) -{ - module_put(trig->ops->owner); - put_device(&trig->dev); -}; - -static inline void iio_get_trigger(struct iio_trigger *trig) -{ - get_device(&trig->dev); - __module_get(trig->ops->owner); -}; - -/** - * iio_trigger_register() - register a trigger with the IIO core - * @trig_info: trigger to be registered - **/ -int iio_trigger_register(struct iio_trigger *trig_info); - -/** - * iio_trigger_unregister() - unregister a trigger from the core - * @trig_info: trigger to be unregistered - **/ -void iio_trigger_unregister(struct iio_trigger *trig_info); - -/** - * iio_trigger_poll() - called on a trigger occurring - * @trig: trigger which occurred - * - * Typically called in relevant hardware interrupt handler. - **/ -void iio_trigger_poll(struct iio_trigger *trig, s64 time); -void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time); - -irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); - -__printf(1, 2) struct iio_trigger *iio_allocate_trigger(const char *fmt, ...); -void iio_free_trigger(struct iio_trigger *trig); - -#endif /* _IIO_TRIGGER_H_ */ diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 665653d79f02..999fd2e00e81 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -15,8 +15,8 @@ #include -#include "../iio.h" -#include "../trigger.h" +#include +#include struct bfin_timer { unsigned short id, bit; diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c index a3465947235e..95fd2f780f52 100644 --- a/drivers/staging/iio/trigger/iio-trig-gpio.c +++ b/drivers/staging/iio/trigger/iio-trig-gpio.c @@ -22,8 +22,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include static LIST_HEAD(iio_gpio_trigger_list); static DEFINE_MUTEX(iio_gpio_trigger_list_lock); diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c index a80cf67bf84d..2c3ccda745eb 100644 --- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c @@ -16,8 +16,8 @@ #include #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include static LIST_HEAD(iio_prtc_trigger_list); static DEFINE_MUTEX(iio_prtc_trigger_list_lock); diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c index 174dc65709d5..404ef192f89f 100644 --- a/drivers/staging/iio/trigger/iio-trig-sysfs.c +++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c @@ -11,8 +11,8 @@ #include #include -#include "../iio.h" -#include "../trigger.h" +#include +#include struct iio_sysfs_trig { struct iio_trigger *trig; diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h deleted file mode 100644 index 60d64b356945..000000000000 --- a/drivers/staging/iio/trigger_consumer.h +++ /dev/null @@ -1,52 +0,0 @@ -/* The industrial I/O core, trigger consumer functions - * - * Copyright (c) 2008-2011 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -/** - * struct iio_poll_func - poll function pair - * - * @indio_dev: data specific to device (passed into poll func) - * @h: the function that is actually run on trigger - * @thread: threaded interrupt part - * @type: the type of interrupt (basically if oneshot) - * @name: name used to identify the trigger consumer. - * @irq: the corresponding irq as allocated from the - * trigger pool - * @timestamp: some devices need a timestamp grabbed as soon - * as possible after the trigger - hence handler - * passes it via here. - **/ -struct iio_poll_func { - struct iio_dev *indio_dev; - irqreturn_t (*h)(int irq, void *p); - irqreturn_t (*thread)(int irq, void *p); - int type; - char *name; - int irq; - s64 timestamp; -}; - - -struct iio_poll_func -*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), - irqreturn_t (*thread)(int irq, void *p), - int type, - struct iio_dev *indio_dev, - const char *fmt, - ...); -void iio_dealloc_pollfunc(struct iio_poll_func *pf); -irqreturn_t iio_pollfunc_store_time(int irq, void *p); - -void iio_trigger_notify_done(struct iio_trigger *trig); - -/* - * Two functions for common case where all that happens is a pollfunc - * is attached and detached from a trigger - */ -int iio_triggered_buffer_postenable(struct iio_dev *indio_dev); -int iio_triggered_buffer_predisable(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/types.h b/drivers/staging/iio/types.h deleted file mode 100644 index 0c3213666901..000000000000 --- a/drivers/staging/iio/types.h +++ /dev/null @@ -1,53 +0,0 @@ -/* industrial I/O data types needed both in and out of kernel - * - * Copyright (c) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ - -#ifndef _IIO_TYPES_H_ -#define _IIO_TYPES_H_ - -enum iio_chan_type { - /* real channel types */ - IIO_VOLTAGE, - IIO_CURRENT, - IIO_POWER, - IIO_ACCEL, - IIO_ANGL_VEL, - IIO_MAGN, - IIO_LIGHT, - IIO_INTENSITY, - IIO_PROXIMITY, - IIO_TEMP, - IIO_INCLI, - IIO_ROT, - IIO_ANGL, - IIO_TIMESTAMP, - IIO_CAPACITANCE, -}; - -enum iio_modifier { - IIO_NO_MOD, - IIO_MOD_X, - IIO_MOD_Y, - IIO_MOD_Z, - IIO_MOD_X_AND_Y, - IIO_MOD_X_AND_Z, - IIO_MOD_Y_AND_Z, - IIO_MOD_X_AND_Y_AND_Z, - IIO_MOD_X_OR_Y, - IIO_MOD_X_OR_Z, - IIO_MOD_Y_OR_Z, - IIO_MOD_X_OR_Y_OR_Z, - IIO_MOD_LIGHT_BOTH, - IIO_MOD_LIGHT_IR, -}; - -#define IIO_VAL_INT 1 -#define IIO_VAL_INT_PLUS_MICRO 2 -#define IIO_VAL_INT_PLUS_NANO 3 - -#endif /* _IIO_TYPES_H_ */ diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h new file mode 100644 index 000000000000..fb0fe46fd659 --- /dev/null +++ b/include/linux/iio/buffer.h @@ -0,0 +1,191 @@ +/* The industrial I/O core - generic buffer interfaces. + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _IIO_BUFFER_GENERIC_H_ +#define _IIO_BUFFER_GENERIC_H_ +#include +#include + +#ifdef CONFIG_IIO_BUFFER + +struct iio_buffer; + +/** + * struct iio_buffer_access_funcs - access functions for buffers. + * @store_to: actually store stuff to the buffer + * @read_first_n: try to get a specified number of bytes (must exist) + * @request_update: if a parameter change has been marked, update underlying + * storage. + * @get_bytes_per_datum:get current bytes per datum + * @set_bytes_per_datum:set number of bytes per datum + * @get_length: get number of datums in buffer + * @set_length: set number of datums in buffer + * + * The purpose of this structure is to make the buffer element + * modular as event for a given driver, different usecases may require + * different buffer designs (space efficiency vs speed for example). + * + * It is worth noting that a given buffer implementation may only support a + * small proportion of these functions. The core code 'should' cope fine with + * any of them not existing. + **/ +struct iio_buffer_access_funcs { + int (*store_to)(struct iio_buffer *buffer, u8 *data, s64 timestamp); + int (*read_first_n)(struct iio_buffer *buffer, + size_t n, + char __user *buf); + + int (*request_update)(struct iio_buffer *buffer); + + int (*get_bytes_per_datum)(struct iio_buffer *buffer); + int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); + int (*get_length)(struct iio_buffer *buffer); + int (*set_length)(struct iio_buffer *buffer, int length); +}; + +/** + * struct iio_buffer - general buffer structure + * @length: [DEVICE] number of datums in buffer + * @bytes_per_datum: [DEVICE] size of individual datum including timestamp + * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode + * control method is used + * @scan_mask: [INTERN] bitmask used in masking scan mode elements + * @scan_timestamp: [INTERN] does the scan mode include a timestamp + * @access: [DRIVER] buffer access functions associated with the + * implementation. + * @scan_el_dev_attr_list:[INTERN] list of scan element related attributes. + * @scan_el_group: [DRIVER] attribute group for those attributes not + * created from the iio_chan_info array. + * @pollq: [INTERN] wait queue to allow for polling on the buffer. + * @stufftoread: [INTERN] flag to indicate new data. + * @demux_list: [INTERN] list of operations required to demux the scan. + * @demux_bounce: [INTERN] buffer for doing gather from incoming scan. + **/ +struct iio_buffer { + int length; + int bytes_per_datum; + struct attribute_group *scan_el_attrs; + long *scan_mask; + bool scan_timestamp; + const struct iio_buffer_access_funcs *access; + struct list_head scan_el_dev_attr_list; + struct attribute_group scan_el_group; + wait_queue_head_t pollq; + bool stufftoread; + const struct attribute_group *attrs; + struct list_head demux_list; + unsigned char *demux_bounce; +}; + +/** + * iio_buffer_init() - Initialize the buffer structure + * @buffer: buffer to be initialized + **/ +void iio_buffer_init(struct iio_buffer *buffer); + +/** + * __iio_update_buffer() - update common elements of buffers + * @buffer: buffer that is the event source + * @bytes_per_datum: size of individual datum including timestamp + * @length: number of datums in buffer + **/ +static inline void __iio_update_buffer(struct iio_buffer *buffer, + int bytes_per_datum, int length) +{ + buffer->bytes_per_datum = bytes_per_datum; + buffer->length = length; +} + +int iio_scan_mask_query(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit); + +/** + * iio_scan_mask_set() - set particular bit in the scan mask + * @buffer: the buffer whose scan mask we are interested in + * @bit: the bit to be set. + **/ +int iio_scan_mask_set(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit); + +/** + * iio_push_to_buffer() - push to a registered buffer. + * @buffer: IIO buffer structure for device + * @scan: Full scan. + * @timestamp: + */ +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, + s64 timestamp); + +int iio_update_demux(struct iio_dev *indio_dev); + +/** + * iio_buffer_register() - register the buffer with IIO core + * @indio_dev: device with the buffer to be registered + **/ +int iio_buffer_register(struct iio_dev *indio_dev, + const struct iio_chan_spec *channels, + int num_channels); + +/** + * iio_buffer_unregister() - unregister the buffer from IIO core + * @indio_dev: the device with the buffer to be unregistered + **/ +void iio_buffer_unregister(struct iio_dev *indio_dev); + +/** + * iio_buffer_read_length() - attr func to get number of datums in the buffer + **/ +ssize_t iio_buffer_read_length(struct device *dev, + struct device_attribute *attr, + char *buf); +/** + * iio_buffer_write_length() - attr func to set number of datums in the buffer + **/ +ssize_t iio_buffer_write_length(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len); +/** + * iio_buffer_store_enable() - attr to turn the buffer on + **/ +ssize_t iio_buffer_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len); +/** + * iio_buffer_show_enable() - attr to see if the buffer is on + **/ +ssize_t iio_buffer_show_enable(struct device *dev, + struct device_attribute *attr, + char *buf); +#define IIO_BUFFER_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ + iio_buffer_read_length, \ + iio_buffer_write_length) + +#define IIO_BUFFER_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ + iio_buffer_show_enable, \ + iio_buffer_store_enable) + +int iio_sw_buffer_preenable(struct iio_dev *indio_dev); + +#else /* CONFIG_IIO_BUFFER */ + +static inline int iio_buffer_register(struct iio_dev *indio_dev, + struct iio_chan_spec *channels, + int num_channels) +{ + return 0; +} + +static inline void iio_buffer_unregister(struct iio_dev *indio_dev) +{}; + +#endif /* CONFIG_IIO_BUFFER */ + +#endif /* _IIO_BUFFER_GENERIC_H_ */ diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h new file mode 100644 index 000000000000..1a15e560a5a1 --- /dev/null +++ b/include/linux/iio/consumer.h @@ -0,0 +1,96 @@ +/* + * Industrial I/O in kernel consumer interface + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _IIO_INKERN_CONSUMER_H_ +#define _IIO_INKERN_CONSUMER_H +#include + +struct iio_dev; +struct iio_chan_spec; + +/** + * struct iio_channel - everything needed for a consumer to use a channel + * @indio_dev: Device on which the channel exists. + * @channel: Full description of the channel. + */ +struct iio_channel { + struct iio_dev *indio_dev; + const struct iio_chan_spec *channel; +}; + +/** + * iio_channel_get() - get description of all that is needed to access channel. + * @name: Unique name of the device as provided in the iio_map + * with which the desired provider to consumer mapping + * was registered. + * @consumer_channel: Unique name to identify the channel on the consumer + * side. This typically describes the channels use within + * the consumer. E.g. 'battery_voltage' + */ +struct iio_channel *iio_st_channel_get(const char *name, + const char *consumer_channel); + +/** + * iio_st_channel_release() - release channels obtained via iio_st_channel_get + * @chan: The channel to be released. + */ +void iio_st_channel_release(struct iio_channel *chan); + +/** + * iio_st_channel_get_all() - get all channels associated with a client + * @name: name of consumer device. + * + * Returns an array of iio_channel structures terminated with one with + * null iio_dev pointer. + * This function is used by fairly generic consumers to get all the + * channels registered as having this consumer. + */ +struct iio_channel *iio_st_channel_get_all(const char *name); + +/** + * iio_st_channel_release_all() - reverse iio_st_get_all + * @chan: Array of channels to be released. + */ +void iio_st_channel_release_all(struct iio_channel *chan); + +/** + * iio_st_read_channel_raw() - read from a given channel + * @channel: The channel being queried. + * @val: Value read back. + * + * Note raw reads from iio channels are in adc counts and hence + * scale will need to be applied if standard units required. + */ +int iio_st_read_channel_raw(struct iio_channel *chan, + int *val); + +/** + * iio_st_get_channel_type() - get the type of a channel + * @channel: The channel being queried. + * @type: The type of the channel. + * + * returns the enum iio_chan_type of the channel + */ +int iio_st_get_channel_type(struct iio_channel *channel, + enum iio_chan_type *type); + +/** + * iio_st_read_channel_scale() - read the scale value for a channel + * @channel: The channel being queried. + * @val: First part of value read back. + * @val2: Second part of value read back. + * + * Note returns a description of what is in val and val2, such + * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val + * + val2/1e6 + */ +int iio_st_read_channel_scale(struct iio_channel *chan, int *val, + int *val2); + +#endif diff --git a/include/linux/iio/driver.h b/include/linux/iio/driver.h new file mode 100644 index 000000000000..a4f8b2e05af5 --- /dev/null +++ b/include/linux/iio/driver.h @@ -0,0 +1,34 @@ +/* + * Industrial I/O in kernel access map interface. + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _IIO_INKERN_H_ +#define _IIO_INKERN_H_ + +struct iio_map; + +/** + * iio_map_array_register() - tell the core about inkernel consumers + * @indio_dev: provider device + * @map: array of mappings specifying association of channel with client + */ +int iio_map_array_register(struct iio_dev *indio_dev, + struct iio_map *map); + +/** + * iio_map_array_unregister() - tell the core to remove consumer mappings + * @indio_dev: provider device + * @map: array of mappings to remove. Note these must have same memory + * addresses as those originally added not just equal parameter + * values. + */ +int iio_map_array_unregister(struct iio_dev *indio_dev, + struct iio_map *map); + +#endif diff --git a/include/linux/iio/events.h b/include/linux/iio/events.h new file mode 100644 index 000000000000..b5acbf93c5da --- /dev/null +++ b/include/linux/iio/events.h @@ -0,0 +1,105 @@ +/* The industrial I/O - event passing to userspace + * + * Copyright (c) 2008-2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _IIO_EVENTS_H_ +#define _IIO_EVENTS_H_ + +#include +#include +#include + +/** + * struct iio_event_data - The actual event being pushed to userspace + * @id: event identifier + * @timestamp: best estimate of time of event occurrence (often from + * the interrupt handler) + */ +struct iio_event_data { + __u64 id; + __s64 timestamp; +}; + +#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int) + +enum iio_event_type { + IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, + IIO_EV_TYPE_ROC, + IIO_EV_TYPE_THRESH_ADAPTIVE, + IIO_EV_TYPE_MAG_ADAPTIVE, +}; + +enum iio_event_direction { + IIO_EV_DIR_EITHER, + IIO_EV_DIR_RISING, + IIO_EV_DIR_FALLING, +}; + +/** + * IIO_EVENT_CODE() - create event identifier + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @diff: Whether the event is for an differential channel or not. + * @modifier: Modifier for the channel. Should be one of enum iio_modifier. + * @direction: Direction of the event. One of enum iio_event_direction. + * @type: Type of the event. Should be one enum iio_event_type. + * @chan: Channel number for non-differential channels. + * @chan1: First channel number for differential channels. + * @chan2: Second channel number for differential channels. + */ + +#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \ + type, chan, chan1, chan2) \ + (((u64)type << 56) | ((u64)diff << 55) | \ + ((u64)direction << 48) | ((u64)modifier << 40) | \ + ((u64)chan_type << 32) | (((u16)chan2) << 16) | ((u16)chan1) | \ + ((u16)chan)) + + +#define IIO_EV_DIR_MAX 4 +#define IIO_EV_BIT(type, direction) \ + (1 << (type*IIO_EV_DIR_MAX + direction)) + +/** + * IIO_MOD_EVENT_CODE() - create event identifier for modified channels + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @number: Channel number. + * @modifier: Modifier for the channel. Should be one of enum iio_modifier. + * @type: Type of the event. Should be one enum iio_event_type. + * @direction: Direction of the event. One of enum iio_event_direction. + */ + +#define IIO_MOD_EVENT_CODE(chan_type, number, modifier, \ + type, direction) \ + IIO_EVENT_CODE(chan_type, 0, modifier, direction, type, number, 0, 0) + +/** + * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @number: Channel number. + * @type: Type of the event. Should be one enum iio_event_type. + * @direction: Direction of the event. One of enum iio_event_direction. + */ + +#define IIO_UNMOD_EVENT_CODE(chan_type, number, type, direction) \ + IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0) + +#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) + +#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) + +#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF) + +/* Event code number extraction depends on which type of event we have. + * Perhaps review this function in the future*/ +#define IIO_EVENT_CODE_EXTRACT_CHAN(mask) ((__s16)(mask & 0xFFFF)) +#define IIO_EVENT_CODE_EXTRACT_CHAN2(mask) ((__s16)(((mask) >> 16) & 0xFFFF)) + +#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) +#define IIO_EVENT_CODE_EXTRACT_DIFF(mask) (((mask) >> 55) & 0x1) + +#endif diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h new file mode 100644 index 000000000000..9c0908a70466 --- /dev/null +++ b/include/linux/iio/iio.h @@ -0,0 +1,463 @@ + +/* The industrial I/O core + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _INDUSTRIAL_IO_H_ +#define _INDUSTRIAL_IO_H_ + +#include +#include +#include +/* IIO TODO LIST */ +/* + * Provide means of adjusting timer accuracy. + * Currently assumes nano seconds. + */ + +enum iio_chan_info_enum { + IIO_CHAN_INFO_RAW = 0, + IIO_CHAN_INFO_PROCESSED, + IIO_CHAN_INFO_SCALE, + IIO_CHAN_INFO_OFFSET, + IIO_CHAN_INFO_CALIBSCALE, + IIO_CHAN_INFO_CALIBBIAS, + IIO_CHAN_INFO_PEAK, + IIO_CHAN_INFO_PEAK_SCALE, + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW, + IIO_CHAN_INFO_AVERAGE_RAW, + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY, + IIO_CHAN_INFO_SAMP_FREQ, +}; + +#define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) +#define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) + +#define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) +#define IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PROCESSED) +#define IIO_CHAN_INFO_SCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SCALE) +#define IIO_CHAN_INFO_SCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SCALE) +#define IIO_CHAN_INFO_OFFSET_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_OFFSET) +#define IIO_CHAN_INFO_OFFSET_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_OFFSET) +#define IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBSCALE) +#define IIO_CHAN_INFO_CALIBSCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBSCALE) +#define IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBBIAS) +#define IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBBIAS) +#define IIO_CHAN_INFO_PEAK_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAK) +#define IIO_CHAN_INFO_PEAK_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAK) +#define IIO_CHAN_INFO_PEAKSCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAKSCALE) +#define IIO_CHAN_INFO_PEAKSCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAKSCALE) +#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT( \ + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) +#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT( \ + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) +#define IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_AVERAGE_RAW) +#define IIO_CHAN_INFO_AVERAGE_RAW_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_AVERAGE_RAW) +#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT( \ + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) +#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT( \ + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) +#define IIO_CHAN_INFO_SAMP_FREQ_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SAMP_FREQ) +#define IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SAMP_FREQ) + +enum iio_endian { + IIO_CPU, + IIO_BE, + IIO_LE, +}; + +struct iio_chan_spec; +struct iio_dev; + +/** + * struct iio_chan_spec_ext_info - Extended channel info attribute + * @name: Info attribute name + * @shared: Whether this attribute is shared between all channels. + * @read: Read callback for this info attribute, may be NULL. + * @write: Write callback for this info attribute, may be NULL. + */ +struct iio_chan_spec_ext_info { + const char *name; + bool shared; + ssize_t (*read)(struct iio_dev *, struct iio_chan_spec const *, + char *buf); + ssize_t (*write)(struct iio_dev *, struct iio_chan_spec const *, + const char *buf, size_t len); +}; + +/** + * struct iio_chan_spec - specification of a single channel + * @type: What type of measurement is the channel making. + * @channel: What number or name do we wish to assign the channel. + * @channel2: If there is a second number for a differential + * channel then this is it. If modified is set then the + * value here specifies the modifier. + * @address: Driver specific identifier. + * @scan_index: Monotonic index to give ordering in scans when read + * from a buffer. + * @scan_type: Sign: 's' or 'u' to specify signed or unsigned + * realbits: Number of valid bits of data + * storage_bits: Realbits + padding + * shift: Shift right by this before masking out + * realbits. + * endianness: little or big endian + * @info_mask: What information is to be exported about this channel. + * This includes calibbias, scale etc. + * @event_mask: What events can this channel produce. + * @ext_info: Array of extended info attributes for this channel. + * The array is NULL terminated, the last element should + * have it's name field set to NULL. + * @extend_name: Allows labeling of channel attributes with an + * informative name. Note this has no effect codes etc, + * unlike modifiers. + * @datasheet_name: A name used in in kernel mapping of channels. It should + * correspond to the first name that the channel is referred + * to by in the datasheet (e.g. IND), or the nearest + * possible compound name (e.g. IND-INC). + * @modified: Does a modifier apply to this channel. What these are + * depends on the channel type. Modifier is set in + * channel2. Examples are IIO_MOD_X for axial sensors about + * the 'x' axis. + * @indexed: Specify the channel has a numerical index. If not, + * the value in channel will be suppressed for attribute + * but not for event codes. Typically set it to 0 when + * the index is false. + * @differential: Channel is differential. + */ +struct iio_chan_spec { + enum iio_chan_type type; + int channel; + int channel2; + unsigned long address; + int scan_index; + struct { + char sign; + u8 realbits; + u8 storagebits; + u8 shift; + enum iio_endian endianness; + } scan_type; + long info_mask; + long event_mask; + const struct iio_chan_spec_ext_info *ext_info; + const char *extend_name; + const char *datasheet_name; + unsigned modified:1; + unsigned indexed:1; + unsigned output:1; + unsigned differential:1; +}; + +#define IIO_ST(si, rb, sb, sh) \ + { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } + +#define IIO_CHAN_SOFT_TIMESTAMP(_si) \ + { .type = IIO_TIMESTAMP, .channel = -1, \ + .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) } + +/** + * iio_get_time_ns() - utility function to get a time stamp for events etc + **/ +static inline s64 iio_get_time_ns(void) +{ + struct timespec ts; + /* + * calls getnstimeofday. + * If hrtimers then up to ns accurate, if not microsecond. + */ + ktime_get_real_ts(&ts); + + return timespec_to_ns(&ts); +} + +/* Device operating modes */ +#define INDIO_DIRECT_MODE 0x01 +#define INDIO_BUFFER_TRIGGERED 0x02 +#define INDIO_BUFFER_HARDWARE 0x08 + +#define INDIO_ALL_BUFFER_MODES \ + (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE) + +struct iio_trigger; /* forward declaration */ +struct iio_dev; + +/** + * struct iio_info - constant information about device + * @driver_module: module structure used to ensure correct + * ownership of chrdevs etc + * @event_attrs: event control attributes + * @attrs: general purpose device attributes + * @read_raw: function to request a value from the device. + * mask specifies which value. Note 0 means a reading of + * the channel in question. Return value will specify the + * type of value returned by the device. val and val2 will + * contain the elements making up the returned value. + * @write_raw: function to write a value to the device. + * Parameters are the same as for read_raw. + * @write_raw_get_fmt: callback function to query the expected + * format/precision. If not set by the driver, write_raw + * returns IIO_VAL_INT_PLUS_MICRO. + * @read_event_config: find out if the event is enabled. + * @write_event_config: set if the event is enabled. + * @read_event_value: read a value associated with the event. Meaning + * is event dependant. event_code specifies which event. + * @write_event_value: write the value associated with the event. + * Meaning is event dependent. + * @validate_trigger: function to validate the trigger when the + * current trigger gets changed. + **/ +struct iio_info { + struct module *driver_module; + struct attribute_group *event_attrs; + const struct attribute_group *attrs; + + int (*read_raw)(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask); + + int (*write_raw)(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask); + + int (*write_raw_get_fmt)(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask); + + int (*read_event_config)(struct iio_dev *indio_dev, + u64 event_code); + + int (*write_event_config)(struct iio_dev *indio_dev, + u64 event_code, + int state); + + int (*read_event_value)(struct iio_dev *indio_dev, + u64 event_code, + int *val); + int (*write_event_value)(struct iio_dev *indio_dev, + u64 event_code, + int val); + int (*validate_trigger)(struct iio_dev *indio_dev, + struct iio_trigger *trig); + int (*update_scan_mode)(struct iio_dev *indio_dev, + const unsigned long *scan_mask); + int (*debugfs_reg_access)(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval); +}; + +/** + * struct iio_buffer_setup_ops - buffer setup related callbacks + * @preenable: [DRIVER] function to run prior to marking buffer enabled + * @postenable: [DRIVER] function to run after marking buffer enabled + * @predisable: [DRIVER] function to run prior to marking buffer + * disabled + * @postdisable: [DRIVER] function to run after marking buffer disabled + */ +struct iio_buffer_setup_ops { + int (*preenable)(struct iio_dev *); + int (*postenable)(struct iio_dev *); + int (*predisable)(struct iio_dev *); + int (*postdisable)(struct iio_dev *); +}; + +/** + * struct iio_dev - industrial I/O device + * @id: [INTERN] used to identify device internally + * @modes: [DRIVER] operating modes supported by device + * @currentmode: [DRIVER] current operating mode + * @dev: [DRIVER] device structure, should be assigned a parent + * and owner + * @event_interface: [INTERN] event chrdevs associated with interrupt lines + * @buffer: [DRIVER] any buffer present + * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux + * @mlock: [INTERN] lock used to prevent simultaneous device state + * changes + * @available_scan_masks: [DRIVER] optional array of allowed bitmasks + * @masklength: [INTERN] the length of the mask established from + * channels + * @active_scan_mask: [INTERN] union of all scan masks requested by buffers + * @scan_timestamp: [INTERN] set if any buffers have requested timestamp + * @scan_index_timestamp:[INTERN] cache of the index to the timestamp + * @trig: [INTERN] current device trigger (buffer modes) + * @pollfunc: [DRIVER] function run on trigger being received + * @channels: [DRIVER] channel specification structure table + * @num_channels: [DRIVER] number of chanels specified in @channels. + * @channel_attr_list: [INTERN] keep track of automatically created channel + * attributes + * @chan_attr_group: [INTERN] group for all attrs in base directory + * @name: [DRIVER] name of the device. + * @info: [DRIVER] callbacks and constant info from driver + * @info_exist_lock: [INTERN] lock to prevent use during removal + * @setup_ops: [DRIVER] callbacks to call before and after buffer + * enable/disable + * @chrdev: [INTERN] associated character device + * @groups: [INTERN] attribute groups + * @groupcounter: [INTERN] index of next attribute group + * @flags: [INTERN] file ops related flags including busy flag. + * @debugfs_dentry: [INTERN] device specific debugfs dentry. + * @cached_reg_addr: [INTERN] cached register address for debugfs reads. + */ +struct iio_dev { + int id; + + int modes; + int currentmode; + struct device dev; + + struct iio_event_interface *event_interface; + + struct iio_buffer *buffer; + int scan_bytes; + struct mutex mlock; + + const unsigned long *available_scan_masks; + unsigned masklength; + const unsigned long *active_scan_mask; + bool scan_timestamp; + unsigned scan_index_timestamp; + struct iio_trigger *trig; + struct iio_poll_func *pollfunc; + + struct iio_chan_spec const *channels; + int num_channels; + + struct list_head channel_attr_list; + struct attribute_group chan_attr_group; + const char *name; + const struct iio_info *info; + struct mutex info_exist_lock; + const struct iio_buffer_setup_ops *setup_ops; + struct cdev chrdev; +#define IIO_MAX_GROUPS 6 + const struct attribute_group *groups[IIO_MAX_GROUPS + 1]; + int groupcounter; + + unsigned long flags; +#if defined(CONFIG_DEBUG_FS) + struct dentry *debugfs_dentry; + unsigned cached_reg_addr; +#endif +}; + +/** + * iio_find_channel_from_si() - get channel from its scan index + * @indio_dev: device + * @si: scan index to match + */ +const struct iio_chan_spec +*iio_find_channel_from_si(struct iio_dev *indio_dev, int si); + +/** + * iio_device_register() - register a device with the IIO subsystem + * @indio_dev: Device structure filled by the device driver + **/ +int iio_device_register(struct iio_dev *indio_dev); + +/** + * iio_device_unregister() - unregister a device from the IIO subsystem + * @indio_dev: Device structure representing the device. + **/ +void iio_device_unregister(struct iio_dev *indio_dev); + +/** + * iio_push_event() - try to add event to the list for userspace reading + * @indio_dev: IIO device structure + * @ev_code: What event + * @timestamp: When the event occurred + **/ +int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp); + +extern struct bus_type iio_bus_type; + +/** + * iio_put_device() - reference counted deallocation of struct device + * @dev: the iio_device containing the device + **/ +static inline void iio_put_device(struct iio_dev *indio_dev) +{ + if (indio_dev) + put_device(&indio_dev->dev); +}; + +/* Can we make this smaller? */ +#define IIO_ALIGN L1_CACHE_BYTES +/** + * iio_allocate_device() - allocate an iio_dev from a driver + * @sizeof_priv: Space to allocate for private structure. + **/ +struct iio_dev *iio_allocate_device(int sizeof_priv); + +static inline void *iio_priv(const struct iio_dev *indio_dev) +{ + return (char *)indio_dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN); +} + +static inline struct iio_dev *iio_priv_to_dev(void *priv) +{ + return (struct iio_dev *)((char *)priv - + ALIGN(sizeof(struct iio_dev), IIO_ALIGN)); +} + +/** + * iio_free_device() - free an iio_dev from a driver + * @dev: the iio_dev associated with the device + **/ +void iio_free_device(struct iio_dev *indio_dev); + +/** + * iio_buffer_enabled() - helper function to test if the buffer is enabled + * @indio_dev: IIO device info structure for device + **/ +static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) +{ + return indio_dev->currentmode + & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); +}; + +/** + * iio_get_debugfs_dentry() - helper function to get the debugfs_dentry + * @indio_dev: IIO device info structure for device + **/ +#if defined(CONFIG_DEBUG_FS) +static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) +{ + return indio_dev->debugfs_dentry; +}; +#else +static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) +{ + return NULL; +}; +#endif + +#endif /* _INDUSTRIAL_IO_H_ */ diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h new file mode 100644 index 000000000000..014d5a13b32b --- /dev/null +++ b/include/linux/iio/kfifo_buf.h @@ -0,0 +1,8 @@ + +#include +#include +#include + +struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); +void iio_kfifo_free(struct iio_buffer *r); + diff --git a/include/linux/iio/machine.h b/include/linux/iio/machine.h new file mode 100644 index 000000000000..0b1f19bfdc44 --- /dev/null +++ b/include/linux/iio/machine.h @@ -0,0 +1,24 @@ +/* + * Industrial I/O in kernel access map definitions for board files. + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/** + * struct iio_map - description of link between consumer and device channels + * @adc_channel_label: Label used to identify the channel on the provider. + * This is matched against the datasheet_name element + * of struct iio_chan_spec. + * @consumer_dev_name: Name to uniquely identify the consumer device. + * @consumer_channel: Unique name used to idenitify the channel on the + * consumer side. + */ +struct iio_map { + const char *adc_channel_label; + const char *consumer_dev_name; + const char *consumer_channel; +}; diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h new file mode 100644 index 000000000000..bfedb73b850e --- /dev/null +++ b/include/linux/iio/sysfs.h @@ -0,0 +1,117 @@ +/* The industrial I/O core + * + *Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * General attributes + */ + +#ifndef _INDUSTRIAL_IO_SYSFS_H_ +#define _INDUSTRIAL_IO_SYSFS_H_ + +struct iio_chan_spec; + +/** + * struct iio_dev_attr - iio specific device attribute + * @dev_attr: underlying device attribute + * @address: associated register address + * @l: list head for maintaining list of dynamically created attrs. + */ +struct iio_dev_attr { + struct device_attribute dev_attr; + u64 address; + struct list_head l; + struct iio_chan_spec const *c; +}; + +#define to_iio_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct iio_dev_attr, dev_attr) + +ssize_t iio_read_const_attr(struct device *dev, + struct device_attribute *attr, + char *len); + +/** + * struct iio_const_attr - constant device specific attribute + * often used for things like available modes + * @string: attribute string + * @dev_attr: underlying device attribute + */ +struct iio_const_attr { + const char *string; + struct device_attribute dev_attr; +}; + +#define to_iio_const_attr(_dev_attr) \ + container_of(_dev_attr, struct iio_const_attr, dev_attr) + +/* Some attributes will be hard coded (device dependent) and not require an + address, in these cases pass a negative */ +#define IIO_ATTR(_name, _mode, _show, _store, _addr) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .address = _addr } + +#define IIO_DEVICE_ATTR(_name, _mode, _show, _store, _addr) \ + struct iio_dev_attr iio_dev_attr_##_name \ + = IIO_ATTR(_name, _mode, _show, _store, _addr) + +#define IIO_DEVICE_ATTR_NAMED(_vname, _name, _mode, _show, _store, _addr) \ + struct iio_dev_attr iio_dev_attr_##_vname \ + = IIO_ATTR(_name, _mode, _show, _store, _addr) + +#define IIO_CONST_ATTR(_name, _string) \ + struct iio_const_attr iio_const_attr_##_name \ + = { .string = _string, \ + .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} + +#define IIO_CONST_ATTR_NAMED(_vname, _name, _string) \ + struct iio_const_attr iio_const_attr_##_vname \ + = { .string = _string, \ + .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} + +/* Generic attributes of onetype or another */ +/** + * IIO_DEV_ATTR_RESET: resets the device + **/ +#define IIO_DEV_ATTR_RESET(_store) \ + IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0) + +/** + * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency + * @_mode: sysfs file mode/permissions + * @_show: output method for the attribute + * @_store: input method for the attribute + **/ +#define IIO_DEV_ATTR_SAMP_FREQ(_mode, _show, _store) \ + IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) + +/** + * IIO_DEV_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies + * @_show: output method for the attribute + * + * May be mode dependent on some devices + **/ +#define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show) \ + IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0) +/** + * IIO_CONST_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies + * @_string: frequency string for the attribute + * + * Constant version + **/ +#define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \ + IIO_CONST_ATTR(sampling_frequency_available, _string) + +#define IIO_DEV_ATTR_TEMP_RAW(_show) \ + IIO_DEVICE_ATTR(in_temp_raw, S_IRUGO, _show, NULL, 0) + +#define IIO_CONST_ATTR_TEMP_OFFSET(_string) \ + IIO_CONST_ATTR(in_temp_offset, _string) + +#define IIO_CONST_ATTR_TEMP_SCALE(_string) \ + IIO_CONST_ATTR(in_temp_scale, _string) + +#endif /* _INDUSTRIAL_IO_SYSFS_H_ */ diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h new file mode 100644 index 000000000000..1cfca231db8f --- /dev/null +++ b/include/linux/iio/trigger.h @@ -0,0 +1,119 @@ +/* The industrial I/O core, trigger handling functions + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include +#include + +#ifndef _IIO_TRIGGER_H_ +#define _IIO_TRIGGER_H_ + +struct iio_subirq { + bool enabled; +}; + +/** + * struct iio_trigger_ops - operations structure for an iio_trigger. + * @owner: used to monitor usage count of the trigger. + * @set_trigger_state: switch on/off the trigger on demand + * @try_reenable: function to reenable the trigger when the + * use count is zero (may be NULL) + * @validate_device: function to validate the device when the + * current trigger gets changed. + * + * This is typically static const within a driver and shared by + * instances of a given device. + **/ +struct iio_trigger_ops { + struct module *owner; + int (*set_trigger_state)(struct iio_trigger *trig, bool state); + int (*try_reenable)(struct iio_trigger *trig); + int (*validate_device)(struct iio_trigger *trig, + struct iio_dev *indio_dev); +}; + + +/** + * struct iio_trigger - industrial I/O trigger device + * + * @id: [INTERN] unique id number + * @name: [DRIVER] unique name + * @dev: [DRIVER] associated device (if relevant) + * @private_data: [DRIVER] device specific data + * @list: [INTERN] used in maintenance of global trigger list + * @alloc_list: [DRIVER] used for driver specific trigger list + * @use_count: use count for the trigger + * @subirq_chip: [INTERN] associate 'virtual' irq chip. + * @subirq_base: [INTERN] base number for irqs provided by trigger. + * @subirqs: [INTERN] information about the 'child' irqs. + * @pool: [INTERN] bitmap of irqs currently in use. + * @pool_lock: [INTERN] protection of the irq pool. + **/ +struct iio_trigger { + const struct iio_trigger_ops *ops; + int id; + const char *name; + struct device dev; + + void *private_data; + struct list_head list; + struct list_head alloc_list; + int use_count; + + struct irq_chip subirq_chip; + int subirq_base; + + struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER]; + unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; + struct mutex pool_lock; +}; + + +static inline struct iio_trigger *to_iio_trigger(struct device *d) +{ + return container_of(d, struct iio_trigger, dev); +}; + +static inline void iio_put_trigger(struct iio_trigger *trig) +{ + module_put(trig->ops->owner); + put_device(&trig->dev); +}; + +static inline void iio_get_trigger(struct iio_trigger *trig) +{ + get_device(&trig->dev); + __module_get(trig->ops->owner); +}; + +/** + * iio_trigger_register() - register a trigger with the IIO core + * @trig_info: trigger to be registered + **/ +int iio_trigger_register(struct iio_trigger *trig_info); + +/** + * iio_trigger_unregister() - unregister a trigger from the core + * @trig_info: trigger to be unregistered + **/ +void iio_trigger_unregister(struct iio_trigger *trig_info); + +/** + * iio_trigger_poll() - called on a trigger occurring + * @trig: trigger which occurred + * + * Typically called in relevant hardware interrupt handler. + **/ +void iio_trigger_poll(struct iio_trigger *trig, s64 time); +void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time); + +irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); + +__printf(1, 2) struct iio_trigger *iio_allocate_trigger(const char *fmt, ...); +void iio_free_trigger(struct iio_trigger *trig); + +#endif /* _IIO_TRIGGER_H_ */ diff --git a/include/linux/iio/trigger_consumer.h b/include/linux/iio/trigger_consumer.h new file mode 100644 index 000000000000..60d64b356945 --- /dev/null +++ b/include/linux/iio/trigger_consumer.h @@ -0,0 +1,52 @@ +/* The industrial I/O core, trigger consumer functions + * + * Copyright (c) 2008-2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/** + * struct iio_poll_func - poll function pair + * + * @indio_dev: data specific to device (passed into poll func) + * @h: the function that is actually run on trigger + * @thread: threaded interrupt part + * @type: the type of interrupt (basically if oneshot) + * @name: name used to identify the trigger consumer. + * @irq: the corresponding irq as allocated from the + * trigger pool + * @timestamp: some devices need a timestamp grabbed as soon + * as possible after the trigger - hence handler + * passes it via here. + **/ +struct iio_poll_func { + struct iio_dev *indio_dev; + irqreturn_t (*h)(int irq, void *p); + irqreturn_t (*thread)(int irq, void *p); + int type; + char *name; + int irq; + s64 timestamp; +}; + + +struct iio_poll_func +*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + int type, + struct iio_dev *indio_dev, + const char *fmt, + ...); +void iio_dealloc_pollfunc(struct iio_poll_func *pf); +irqreturn_t iio_pollfunc_store_time(int irq, void *p); + +void iio_trigger_notify_done(struct iio_trigger *trig); + +/* + * Two functions for common case where all that happens is a pollfunc + * is attached and detached from a trigger + */ +int iio_triggered_buffer_postenable(struct iio_dev *indio_dev); +int iio_triggered_buffer_predisable(struct iio_dev *indio_dev); diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h new file mode 100644 index 000000000000..0c3213666901 --- /dev/null +++ b/include/linux/iio/types.h @@ -0,0 +1,53 @@ +/* industrial I/O data types needed both in and out of kernel + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _IIO_TYPES_H_ +#define _IIO_TYPES_H_ + +enum iio_chan_type { + /* real channel types */ + IIO_VOLTAGE, + IIO_CURRENT, + IIO_POWER, + IIO_ACCEL, + IIO_ANGL_VEL, + IIO_MAGN, + IIO_LIGHT, + IIO_INTENSITY, + IIO_PROXIMITY, + IIO_TEMP, + IIO_INCLI, + IIO_ROT, + IIO_ANGL, + IIO_TIMESTAMP, + IIO_CAPACITANCE, +}; + +enum iio_modifier { + IIO_NO_MOD, + IIO_MOD_X, + IIO_MOD_Y, + IIO_MOD_Z, + IIO_MOD_X_AND_Y, + IIO_MOD_X_AND_Z, + IIO_MOD_Y_AND_Z, + IIO_MOD_X_AND_Y_AND_Z, + IIO_MOD_X_OR_Y, + IIO_MOD_X_OR_Z, + IIO_MOD_Y_OR_Z, + IIO_MOD_X_OR_Y_OR_Z, + IIO_MOD_LIGHT_BOTH, + IIO_MOD_LIGHT_IR, +}; + +#define IIO_VAL_INT 1 +#define IIO_VAL_INT_PLUS_MICRO 2 +#define IIO_VAL_INT_PLUS_NANO 3 + +#endif /* _IIO_TYPES_H_ */ -- cgit v1.2.3-71-gd317 From db3b9e990e75573402cda22faf933760f076c033 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 26 Apr 2012 12:34:58 -0700 Subject: Staging: VME: move VME drivers out of staging This moves the VME core, VME board drivers, and VME bridge drivers out of the drivers/staging/vme/ area to drivers/vme/. The VME device drivers have not moved out yet due to some API questions they are still working through, that should happen soon, hopefully. Cc: Martyn Welch Cc: Manohar Vanga Cc: Vincent Bossier Cc: "Emilio G. Cota" Signed-off-by: Greg Kroah-Hartman --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/staging/Kconfig | 2 - drivers/staging/vme/Kconfig | 19 - drivers/staging/vme/Makefile | 7 - drivers/staging/vme/TODO | 5 - drivers/staging/vme/boards/Kconfig | 9 - drivers/staging/vme/boards/Makefile | 5 - drivers/staging/vme/boards/vme_vmivme7805.c | 123 -- drivers/staging/vme/boards/vme_vmivme7805.h | 37 - drivers/staging/vme/bridges/Kconfig | 15 - drivers/staging/vme/bridges/Makefile | 2 - drivers/staging/vme/bridges/vme_ca91cx42.c | 1959 ------------------- drivers/staging/vme/bridges/vme_ca91cx42.h | 583 ------ drivers/staging/vme/bridges/vme_tsi148.c | 2691 --------------------------- drivers/staging/vme/bridges/vme_tsi148.h | 1410 -------------- drivers/staging/vme/devices/Kconfig | 3 +- drivers/staging/vme/devices/vme_pio2_cntr.c | 2 +- drivers/staging/vme/devices/vme_pio2_core.c | 2 +- drivers/staging/vme/devices/vme_pio2_gpio.c | 2 +- drivers/staging/vme/devices/vme_user.c | 2 +- drivers/staging/vme/vme.c | 1517 --------------- drivers/staging/vme/vme.h | 174 -- drivers/staging/vme/vme_api.txt | 396 ---- drivers/staging/vme/vme_bridge.h | 174 -- drivers/vme/Kconfig | 19 + drivers/vme/Makefile | 7 + drivers/vme/boards/Kconfig | 9 + drivers/vme/boards/Makefile | 5 + drivers/vme/boards/vme_vmivme7805.c | 123 ++ drivers/vme/boards/vme_vmivme7805.h | 37 + drivers/vme/bridges/Kconfig | 15 + drivers/vme/bridges/Makefile | 2 + drivers/vme/bridges/vme_ca91cx42.c | 1959 +++++++++++++++++++ drivers/vme/bridges/vme_ca91cx42.h | 583 ++++++ drivers/vme/bridges/vme_tsi148.c | 2691 +++++++++++++++++++++++++++ drivers/vme/bridges/vme_tsi148.h | 1410 ++++++++++++++ drivers/vme/vme.c | 1517 +++++++++++++++ drivers/vme/vme_api.txt | 396 ++++ drivers/vme/vme_bridge.h | 174 ++ include/linux/vme.h | 174 ++ 41 files changed, 9130 insertions(+), 9133 deletions(-) delete mode 100644 drivers/staging/vme/Kconfig delete mode 100644 drivers/staging/vme/TODO delete mode 100644 drivers/staging/vme/boards/Kconfig delete mode 100644 drivers/staging/vme/boards/Makefile delete mode 100644 drivers/staging/vme/boards/vme_vmivme7805.c delete mode 100644 drivers/staging/vme/boards/vme_vmivme7805.h delete mode 100644 drivers/staging/vme/bridges/Kconfig delete mode 100644 drivers/staging/vme/bridges/Makefile delete mode 100644 drivers/staging/vme/bridges/vme_ca91cx42.c delete mode 100644 drivers/staging/vme/bridges/vme_ca91cx42.h delete mode 100644 drivers/staging/vme/bridges/vme_tsi148.c delete mode 100644 drivers/staging/vme/bridges/vme_tsi148.h delete mode 100644 drivers/staging/vme/vme.c delete mode 100644 drivers/staging/vme/vme.h delete mode 100644 drivers/staging/vme/vme_api.txt delete mode 100644 drivers/staging/vme/vme_bridge.h create mode 100644 drivers/vme/Kconfig create mode 100644 drivers/vme/Makefile create mode 100644 drivers/vme/boards/Kconfig create mode 100644 drivers/vme/boards/Makefile create mode 100644 drivers/vme/boards/vme_vmivme7805.c create mode 100644 drivers/vme/boards/vme_vmivme7805.h create mode 100644 drivers/vme/bridges/Kconfig create mode 100644 drivers/vme/bridges/Makefile create mode 100644 drivers/vme/bridges/vme_ca91cx42.c create mode 100644 drivers/vme/bridges/vme_ca91cx42.h create mode 100644 drivers/vme/bridges/vme_tsi148.c create mode 100644 drivers/vme/bridges/vme_tsi148.h create mode 100644 drivers/vme/vme.c create mode 100644 drivers/vme/vme_api.txt create mode 100644 drivers/vme/vme_bridge.h create mode 100644 include/linux/vme.h (limited to 'include/linux') diff --git a/drivers/Kconfig b/drivers/Kconfig index 0265cb12cdaa..e245779443da 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -142,4 +142,6 @@ source "drivers/devfreq/Kconfig" source "drivers/iio/Kconfig" +source "drivers/vme/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index cdbe362df0ec..08b78e035468 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -135,3 +135,4 @@ obj-$(CONFIG_HYPERV) += hv/ obj-$(CONFIG_PM_DEVFREQ) += devfreq/ obj-$(CONFIG_IIO) += iio/ +obj-$(CONFIG_VME_BUS) += vme/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 8d406b5938c0..60221efc417b 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -72,8 +72,6 @@ source "drivers/staging/vt6655/Kconfig" source "drivers/staging/vt6656/Kconfig" -source "drivers/staging/vme/Kconfig" - source "drivers/staging/sep/Kconfig" source "drivers/staging/iio/Kconfig" diff --git a/drivers/staging/vme/Kconfig b/drivers/staging/vme/Kconfig deleted file mode 100644 index 6411ae51ed3f..000000000000 --- a/drivers/staging/vme/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# -# VME configuration. -# - -menuconfig VME_BUS - tristate "VME bridge support" - depends on PCI - ---help--- - If you say Y here you get support for the VME bridge Framework. - -if VME_BUS - -source "drivers/staging/vme/bridges/Kconfig" - -source "drivers/staging/vme/devices/Kconfig" - -source "drivers/staging/vme/boards/Kconfig" - -endif # VME diff --git a/drivers/staging/vme/Makefile b/drivers/staging/vme/Makefile index b4ea3f8d0a50..accdb72e39e2 100644 --- a/drivers/staging/vme/Makefile +++ b/drivers/staging/vme/Makefile @@ -1,8 +1 @@ -# -# Makefile for the VME bridge device drivers. -# -obj-$(CONFIG_VME_BUS) += vme.o - -obj-y += bridges/ obj-y += devices/ -obj-y += boards/ diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO deleted file mode 100644 index 79f00333e7ef..000000000000 --- a/drivers/staging/vme/TODO +++ /dev/null @@ -1,5 +0,0 @@ - TODO - ==== - -- Add one or more device drivers which use the VME framework. - diff --git a/drivers/staging/vme/boards/Kconfig b/drivers/staging/vme/boards/Kconfig deleted file mode 100644 index 761631353527..000000000000 --- a/drivers/staging/vme/boards/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -comment "VME Board Drivers" - -config VMIVME_7805 - tristate "VMIVME-7805" - help - If you say Y here you get support for the VMIVME-7805 board. - This board has an additional control interface to the Universe II - chip. This driver has to be included if you want to access VME bus - with VMIVME-7805 board. diff --git a/drivers/staging/vme/boards/Makefile b/drivers/staging/vme/boards/Makefile deleted file mode 100644 index 43658340885d..000000000000 --- a/drivers/staging/vme/boards/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the VME board drivers. -# - -obj-$(CONFIG_VMIVME_7805) += vme_vmivme7805.o diff --git a/drivers/staging/vme/boards/vme_vmivme7805.c b/drivers/staging/vme/boards/vme_vmivme7805.c deleted file mode 100644 index 8e05bb4e135a..000000000000 --- a/drivers/staging/vme/boards/vme_vmivme7805.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Support for the VMIVME-7805 board access to the Universe II bridge. - * - * Author: Arthur Benilov - * Copyright 2010 Ion Beam Application, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -#include "vme_vmivme7805.h" - -static int __init vmic_init(void); -static int vmic_probe(struct pci_dev *, const struct pci_device_id *); -static void vmic_remove(struct pci_dev *); -static void __exit vmic_exit(void); - -/** Base address to access FPGA register */ -static void *vmic_base; - -static const char driver_name[] = "vmivme_7805"; - -static DEFINE_PCI_DEVICE_TABLE(vmic_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_VMIC, PCI_DEVICE_ID_VTIMR) }, - { }, -}; - -static struct pci_driver vmic_driver = { - .name = driver_name, - .id_table = vmic_ids, - .probe = vmic_probe, - .remove = vmic_remove, -}; - -static int __init vmic_init(void) -{ - return pci_register_driver(&vmic_driver); -} - -static int vmic_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int retval; - u32 data; - - /* Enable the device */ - retval = pci_enable_device(pdev); - if (retval) { - dev_err(&pdev->dev, "Unable to enable device\n"); - goto err; - } - - /* Map Registers */ - retval = pci_request_regions(pdev, driver_name); - if (retval) { - dev_err(&pdev->dev, "Unable to reserve resources\n"); - goto err_resource; - } - - /* Map registers in BAR 0 */ - vmic_base = ioremap_nocache(pci_resource_start(pdev, 0), 16); - if (!vmic_base) { - dev_err(&pdev->dev, "Unable to remap CRG region\n"); - retval = -EIO; - goto err_remap; - } - - /* Clear the FPGA VME IF contents */ - iowrite32(0, vmic_base + VME_CONTROL); - - /* Clear any initial BERR */ - data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF; - data |= BM_VME_CONTROL_BERRST; - iowrite32(data, vmic_base + VME_CONTROL); - - /* Enable the vme interface and byte swapping */ - data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF; - data = data | BM_VME_CONTROL_MASTER_ENDIAN | - BM_VME_CONTROL_SLAVE_ENDIAN | - BM_VME_CONTROL_ABLE | - BM_VME_CONTROL_BERRI | - BM_VME_CONTROL_BPENA | - BM_VME_CONTROL_VBENA; - iowrite32(data, vmic_base + VME_CONTROL); - - return 0; - -err_remap: - pci_release_regions(pdev); -err_resource: - pci_disable_device(pdev); -err: - return retval; -} - -static void vmic_remove(struct pci_dev *pdev) -{ - iounmap(vmic_base); - pci_release_regions(pdev); - pci_disable_device(pdev); - -} - -static void __exit vmic_exit(void) -{ - pci_unregister_driver(&vmic_driver); -} - -MODULE_DESCRIPTION("VMIVME-7805 board support driver"); -MODULE_AUTHOR("Arthur Benilov "); -MODULE_LICENSE("GPL"); - -module_init(vmic_init); -module_exit(vmic_exit); - diff --git a/drivers/staging/vme/boards/vme_vmivme7805.h b/drivers/staging/vme/boards/vme_vmivme7805.h deleted file mode 100644 index 44c2c449808c..000000000000 --- a/drivers/staging/vme/boards/vme_vmivme7805.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * vmivme_7805.h - * - * Support for the VMIVME-7805 board access to the Universe II bridge. - * - * Author: Arthur Benilov - * Copyright 2010 Ion Beam Application, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - - -#ifndef _VMIVME_7805_H -#define _VMIVME_7805_H - -#ifndef PCI_VENDOR_ID_VMIC -#define PCI_VENDOR_ID_VMIC 0x114A -#endif - -#ifndef PCI_DEVICE_ID_VTIMR -#define PCI_DEVICE_ID_VTIMR 0x0004 -#endif - -#define VME_CONTROL 0x0000 -#define BM_VME_CONTROL_MASTER_ENDIAN 0x0001 -#define BM_VME_CONTROL_SLAVE_ENDIAN 0x0002 -#define BM_VME_CONTROL_ABLE 0x0004 -#define BM_VME_CONTROL_BERRI 0x0040 -#define BM_VME_CONTROL_BERRST 0x0080 -#define BM_VME_CONTROL_BPENA 0x0400 -#define BM_VME_CONTROL_VBENA 0x0800 - -#endif /* _VMIVME_7805_H */ - diff --git a/drivers/staging/vme/bridges/Kconfig b/drivers/staging/vme/bridges/Kconfig deleted file mode 100644 index 9331064e0476..000000000000 --- a/drivers/staging/vme/bridges/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -comment "VME Bridge Drivers" - -config VME_CA91CX42 - tristate "Universe II" - depends on VIRT_TO_BUS - help - If you say Y here you get support for the Tundra CA91C142 - (Universe II) VME bridge chip. - -config VME_TSI148 - tristate "Tempe" - depends on VIRT_TO_BUS - help - If you say Y here you get support for the Tundra TSI148 VME bridge - chip. diff --git a/drivers/staging/vme/bridges/Makefile b/drivers/staging/vme/bridges/Makefile deleted file mode 100644 index 59638afcd502..000000000000 --- a/drivers/staging/vme/bridges/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_VME_CA91CX42) += vme_ca91cx42.o -obj-$(CONFIG_VME_TSI148) += vme_tsi148.o diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c deleted file mode 100644 index 515b8b8e32a8..000000000000 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ /dev/null @@ -1,1959 +0,0 @@ -/* - * Support for the Tundra Universe I/II VME-PCI Bridge Chips - * - * Author: Martyn Welch - * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. - * - * Based on work by Tom Armistead and Ajit Prem - * Copyright 2004 Motorola Inc. - * - * Derived from ca91c042.c by Michael Wyrick - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../vme.h" -#include "../vme_bridge.h" -#include "vme_ca91cx42.h" - -static int __init ca91cx42_init(void); -static int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *); -static void ca91cx42_remove(struct pci_dev *); -static void __exit ca91cx42_exit(void); - -/* Module parameters */ -static int geoid; - -static const char driver_name[] = "vme_ca91cx42"; - -static DEFINE_PCI_DEVICE_TABLE(ca91cx42_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) }, - { }, -}; - -static struct pci_driver ca91cx42_driver = { - .name = driver_name, - .id_table = ca91cx42_ids, - .probe = ca91cx42_probe, - .remove = ca91cx42_remove, -}; - -static u32 ca91cx42_DMA_irqhandler(struct ca91cx42_driver *bridge) -{ - wake_up(&bridge->dma_queue); - - return CA91CX42_LINT_DMA; -} - -static u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat) -{ - int i; - u32 serviced = 0; - - for (i = 0; i < 4; i++) { - if (stat & CA91CX42_LINT_LM[i]) { - /* We only enable interrupts if the callback is set */ - bridge->lm_callback[i](i); - serviced |= CA91CX42_LINT_LM[i]; - } - } - - return serviced; -} - -/* XXX This needs to be split into 4 queues */ -static u32 ca91cx42_MB_irqhandler(struct ca91cx42_driver *bridge, int mbox_mask) -{ - wake_up(&bridge->mbox_queue); - - return CA91CX42_LINT_MBOX; -} - -static u32 ca91cx42_IACK_irqhandler(struct ca91cx42_driver *bridge) -{ - wake_up(&bridge->iack_queue); - - return CA91CX42_LINT_SW_IACK; -} - -static u32 ca91cx42_VERR_irqhandler(struct vme_bridge *ca91cx42_bridge) -{ - int val; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - val = ioread32(bridge->base + DGCS); - - if (!(val & 0x00000800)) { - dev_err(ca91cx42_bridge->parent, "ca91cx42_VERR_irqhandler DMA " - "Read Error DGCS=%08X\n", val); - } - - return CA91CX42_LINT_VERR; -} - -static u32 ca91cx42_LERR_irqhandler(struct vme_bridge *ca91cx42_bridge) -{ - int val; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - val = ioread32(bridge->base + DGCS); - - if (!(val & 0x00000800)) - dev_err(ca91cx42_bridge->parent, "ca91cx42_LERR_irqhandler DMA " - "Read Error DGCS=%08X\n", val); - - return CA91CX42_LINT_LERR; -} - - -static u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge, - int stat) -{ - int vec, i, serviced = 0; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - - for (i = 7; i > 0; i--) { - if (stat & (1 << i)) { - vec = ioread32(bridge->base + - CA91CX42_V_STATID[i]) & 0xff; - - vme_irq_handler(ca91cx42_bridge, i, vec); - - serviced |= (1 << i); - } - } - - return serviced; -} - -static irqreturn_t ca91cx42_irqhandler(int irq, void *ptr) -{ - u32 stat, enable, serviced = 0; - struct vme_bridge *ca91cx42_bridge; - struct ca91cx42_driver *bridge; - - ca91cx42_bridge = ptr; - - bridge = ca91cx42_bridge->driver_priv; - - enable = ioread32(bridge->base + LINT_EN); - stat = ioread32(bridge->base + LINT_STAT); - - /* Only look at unmasked interrupts */ - stat &= enable; - - if (unlikely(!stat)) - return IRQ_NONE; - - if (stat & CA91CX42_LINT_DMA) - serviced |= ca91cx42_DMA_irqhandler(bridge); - if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | - CA91CX42_LINT_LM3)) - serviced |= ca91cx42_LM_irqhandler(bridge, stat); - if (stat & CA91CX42_LINT_MBOX) - serviced |= ca91cx42_MB_irqhandler(bridge, stat); - if (stat & CA91CX42_LINT_SW_IACK) - serviced |= ca91cx42_IACK_irqhandler(bridge); - if (stat & CA91CX42_LINT_VERR) - serviced |= ca91cx42_VERR_irqhandler(ca91cx42_bridge); - if (stat & CA91CX42_LINT_LERR) - serviced |= ca91cx42_LERR_irqhandler(ca91cx42_bridge); - if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 | - CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 | - CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 | - CA91CX42_LINT_VIRQ7)) - serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat); - - /* Clear serviced interrupts */ - iowrite32(serviced, bridge->base + LINT_STAT); - - return IRQ_HANDLED; -} - -static int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge) -{ - int result, tmp; - struct pci_dev *pdev; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - /* Need pdev */ - pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); - - /* Initialise list for VME bus errors */ - INIT_LIST_HEAD(&ca91cx42_bridge->vme_errors); - - mutex_init(&ca91cx42_bridge->irq_mtx); - - /* Disable interrupts from PCI to VME */ - iowrite32(0, bridge->base + VINT_EN); - - /* Disable PCI interrupts */ - iowrite32(0, bridge->base + LINT_EN); - /* Clear Any Pending PCI Interrupts */ - iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); - - result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED, - driver_name, ca91cx42_bridge); - if (result) { - dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n", - pdev->irq); - return result; - } - - /* Ensure all interrupts are mapped to PCI Interrupt 0 */ - iowrite32(0, bridge->base + LINT_MAP0); - iowrite32(0, bridge->base + LINT_MAP1); - iowrite32(0, bridge->base + LINT_MAP2); - - /* Enable DMA, mailbox & LM Interrupts */ - tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 | - CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK | - CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA; - - iowrite32(tmp, bridge->base + LINT_EN); - - return 0; -} - -static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, - struct pci_dev *pdev) -{ - /* Disable interrupts from PCI to VME */ - iowrite32(0, bridge->base + VINT_EN); - - /* Disable PCI interrupts */ - iowrite32(0, bridge->base + LINT_EN); - /* Clear Any Pending PCI Interrupts */ - iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); - - free_irq(pdev->irq, pdev); -} - -static int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level) -{ - u32 tmp; - - tmp = ioread32(bridge->base + LINT_STAT); - - if (tmp & (1 << level)) - return 0; - else - return 1; -} - -/* - * Set up an VME interrupt - */ -static void ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, - int state, int sync) - -{ - struct pci_dev *pdev; - u32 tmp; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - /* Enable IRQ level */ - tmp = ioread32(bridge->base + LINT_EN); - - if (state == 0) - tmp &= ~CA91CX42_LINT_VIRQ[level]; - else - tmp |= CA91CX42_LINT_VIRQ[level]; - - iowrite32(tmp, bridge->base + LINT_EN); - - if ((state == 0) && (sync != 0)) { - pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, - dev); - - synchronize_irq(pdev->irq); - } -} - -static int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level, - int statid) -{ - u32 tmp; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - /* Universe can only generate even vectors */ - if (statid & 1) - return -EINVAL; - - mutex_lock(&bridge->vme_int); - - tmp = ioread32(bridge->base + VINT_EN); - - /* Set Status/ID */ - iowrite32(statid << 24, bridge->base + STATID); - - /* Assert VMEbus IRQ */ - tmp = tmp | (1 << (level + 24)); - iowrite32(tmp, bridge->base + VINT_EN); - - /* Wait for IACK */ - wait_event_interruptible(bridge->iack_queue, - ca91cx42_iack_received(bridge, level)); - - /* Return interrupt to low state */ - tmp = ioread32(bridge->base + VINT_EN); - tmp = tmp & ~(1 << (level + 24)); - iowrite32(tmp, bridge->base + VINT_EN); - - mutex_unlock(&bridge->vme_int); - - return 0; -} - -static int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, - unsigned long long vme_base, unsigned long long size, - dma_addr_t pci_base, u32 aspace, u32 cycle) -{ - unsigned int i, addr = 0, granularity; - unsigned int temp_ctl = 0; - unsigned int vme_bound, pci_offset; - struct vme_bridge *ca91cx42_bridge; - struct ca91cx42_driver *bridge; - - ca91cx42_bridge = image->parent; - - bridge = ca91cx42_bridge->driver_priv; - - i = image->number; - - switch (aspace) { - case VME_A16: - addr |= CA91CX42_VSI_CTL_VAS_A16; - break; - case VME_A24: - addr |= CA91CX42_VSI_CTL_VAS_A24; - break; - case VME_A32: - addr |= CA91CX42_VSI_CTL_VAS_A32; - break; - case VME_USER1: - addr |= CA91CX42_VSI_CTL_VAS_USER1; - break; - case VME_USER2: - addr |= CA91CX42_VSI_CTL_VAS_USER2; - break; - case VME_A64: - case VME_CRCSR: - case VME_USER3: - case VME_USER4: - default: - dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); - return -EINVAL; - break; - } - - /* - * Bound address is a valid address for the window, adjust - * accordingly - */ - vme_bound = vme_base + size; - pci_offset = pci_base - vme_base; - - if ((i == 0) || (i == 4)) - granularity = 0x1000; - else - granularity = 0x10000; - - if (vme_base & (granularity - 1)) { - dev_err(ca91cx42_bridge->parent, "Invalid VME base " - "alignment\n"); - return -EINVAL; - } - if (vme_bound & (granularity - 1)) { - dev_err(ca91cx42_bridge->parent, "Invalid VME bound " - "alignment\n"); - return -EINVAL; - } - if (pci_offset & (granularity - 1)) { - dev_err(ca91cx42_bridge->parent, "Invalid PCI Offset " - "alignment\n"); - return -EINVAL; - } - - /* Disable while we are mucking around */ - temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); - temp_ctl &= ~CA91CX42_VSI_CTL_EN; - iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); - - /* Setup mapping */ - iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]); - iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]); - iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]); - - /* Setup address space */ - temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; - temp_ctl |= addr; - - /* Setup cycle types */ - temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); - if (cycle & VME_SUPER) - temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; - if (cycle & VME_USER) - temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; - if (cycle & VME_PROG) - temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; - if (cycle & VME_DATA) - temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; - - /* Write ctl reg without enable */ - iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); - - if (enabled) - temp_ctl |= CA91CX42_VSI_CTL_EN; - - iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); - - return 0; -} - -static int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, - unsigned long long *vme_base, unsigned long long *size, - dma_addr_t *pci_base, u32 *aspace, u32 *cycle) -{ - unsigned int i, granularity = 0, ctl = 0; - unsigned long long vme_bound, pci_offset; - struct ca91cx42_driver *bridge; - - bridge = image->parent->driver_priv; - - i = image->number; - - if ((i == 0) || (i == 4)) - granularity = 0x1000; - else - granularity = 0x10000; - - /* Read Registers */ - ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); - - *vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]); - vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]); - pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]); - - *pci_base = (dma_addr_t)vme_base + pci_offset; - *size = (unsigned long long)((vme_bound - *vme_base) + granularity); - - *enabled = 0; - *aspace = 0; - *cycle = 0; - - if (ctl & CA91CX42_VSI_CTL_EN) - *enabled = 1; - - if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) - *aspace = VME_A16; - if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) - *aspace = VME_A24; - if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) - *aspace = VME_A32; - if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) - *aspace = VME_USER1; - if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) - *aspace = VME_USER2; - - if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) - *cycle |= VME_SUPER; - if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) - *cycle |= VME_USER; - if (ctl & CA91CX42_VSI_CTL_PGM_PGM) - *cycle |= VME_PROG; - if (ctl & CA91CX42_VSI_CTL_PGM_DATA) - *cycle |= VME_DATA; - - return 0; -} - -/* - * Allocate and map PCI Resource - */ -static int ca91cx42_alloc_resource(struct vme_master_resource *image, - unsigned long long size) -{ - unsigned long long existing_size; - int retval = 0; - struct pci_dev *pdev; - struct vme_bridge *ca91cx42_bridge; - - ca91cx42_bridge = image->parent; - - /* Find pci_dev container of dev */ - if (ca91cx42_bridge->parent == NULL) { - dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); - return -EINVAL; - } - pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); - - existing_size = (unsigned long long)(image->bus_resource.end - - image->bus_resource.start); - - /* If the existing size is OK, return */ - if (existing_size == (size - 1)) - return 0; - - if (existing_size != 0) { - iounmap(image->kern_base); - image->kern_base = NULL; - kfree(image->bus_resource.name); - release_resource(&image->bus_resource); - memset(&image->bus_resource, 0, sizeof(struct resource)); - } - - if (image->bus_resource.name == NULL) { - image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); - if (image->bus_resource.name == NULL) { - dev_err(ca91cx42_bridge->parent, "Unable to allocate " - "memory for resource name\n"); - retval = -ENOMEM; - goto err_name; - } - } - - sprintf((char *)image->bus_resource.name, "%s.%d", - ca91cx42_bridge->name, image->number); - - image->bus_resource.start = 0; - image->bus_resource.end = (unsigned long)size; - image->bus_resource.flags = IORESOURCE_MEM; - - retval = pci_bus_alloc_resource(pdev->bus, - &image->bus_resource, size, size, PCIBIOS_MIN_MEM, - 0, NULL, NULL); - if (retval) { - dev_err(ca91cx42_bridge->parent, "Failed to allocate mem " - "resource for window %d size 0x%lx start 0x%lx\n", - image->number, (unsigned long)size, - (unsigned long)image->bus_resource.start); - goto err_resource; - } - - image->kern_base = ioremap_nocache( - image->bus_resource.start, size); - if (image->kern_base == NULL) { - dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); - retval = -ENOMEM; - goto err_remap; - } - - return 0; - -err_remap: - release_resource(&image->bus_resource); -err_resource: - kfree(image->bus_resource.name); - memset(&image->bus_resource, 0, sizeof(struct resource)); -err_name: - return retval; -} - -/* - * Free and unmap PCI Resource - */ -static void ca91cx42_free_resource(struct vme_master_resource *image) -{ - iounmap(image->kern_base); - image->kern_base = NULL; - release_resource(&image->bus_resource); - kfree(image->bus_resource.name); - memset(&image->bus_resource, 0, sizeof(struct resource)); -} - - -static int ca91cx42_master_set(struct vme_master_resource *image, int enabled, - unsigned long long vme_base, unsigned long long size, u32 aspace, - u32 cycle, u32 dwidth) -{ - int retval = 0; - unsigned int i, granularity = 0; - unsigned int temp_ctl = 0; - unsigned long long pci_bound, vme_offset, pci_base; - struct vme_bridge *ca91cx42_bridge; - struct ca91cx42_driver *bridge; - - ca91cx42_bridge = image->parent; - - bridge = ca91cx42_bridge->driver_priv; - - i = image->number; - - if ((i == 0) || (i == 4)) - granularity = 0x1000; - else - granularity = 0x10000; - - /* Verify input data */ - if (vme_base & (granularity - 1)) { - dev_err(ca91cx42_bridge->parent, "Invalid VME Window " - "alignment\n"); - retval = -EINVAL; - goto err_window; - } - if (size & (granularity - 1)) { - dev_err(ca91cx42_bridge->parent, "Invalid VME Window " - "alignment\n"); - retval = -EINVAL; - goto err_window; - } - - spin_lock(&image->lock); - - /* - * Let's allocate the resource here rather than further up the stack as - * it avoids pushing loads of bus dependent stuff up the stack - */ - retval = ca91cx42_alloc_resource(image, size); - if (retval) { - spin_unlock(&image->lock); - dev_err(ca91cx42_bridge->parent, "Unable to allocate memory " - "for resource name\n"); - retval = -ENOMEM; - goto err_res; - } - - pci_base = (unsigned long long)image->bus_resource.start; - - /* - * Bound address is a valid address for the window, adjust - * according to window granularity. - */ - pci_bound = pci_base + size; - vme_offset = vme_base - pci_base; - - /* Disable while we are mucking around */ - temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); - temp_ctl &= ~CA91CX42_LSI_CTL_EN; - iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); - - /* Setup cycle types */ - temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; - if (cycle & VME_BLT) - temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; - if (cycle & VME_MBLT) - temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; - - /* Setup data width */ - temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; - switch (dwidth) { - case VME_D8: - temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; - break; - case VME_D16: - temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; - break; - case VME_D32: - temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; - break; - case VME_D64: - temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; - break; - default: - spin_unlock(&image->lock); - dev_err(ca91cx42_bridge->parent, "Invalid data width\n"); - retval = -EINVAL; - goto err_dwidth; - break; - } - - /* Setup address space */ - temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; - switch (aspace) { - case VME_A16: - temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; - break; - case VME_A24: - temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; - break; - case VME_A32: - temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; - break; - case VME_CRCSR: - temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; - break; - case VME_USER1: - temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; - break; - case VME_USER2: - temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; - break; - case VME_A64: - case VME_USER3: - case VME_USER4: - default: - spin_unlock(&image->lock); - dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); - retval = -EINVAL; - goto err_aspace; - break; - } - - temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); - if (cycle & VME_SUPER) - temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; - if (cycle & VME_PROG) - temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; - - /* Setup mapping */ - iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]); - iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]); - iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]); - - /* Write ctl reg without enable */ - iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); - - if (enabled) - temp_ctl |= CA91CX42_LSI_CTL_EN; - - iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); - - spin_unlock(&image->lock); - return 0; - -err_aspace: -err_dwidth: - ca91cx42_free_resource(image); -err_res: -err_window: - return retval; -} - -static int __ca91cx42_master_get(struct vme_master_resource *image, - int *enabled, unsigned long long *vme_base, unsigned long long *size, - u32 *aspace, u32 *cycle, u32 *dwidth) -{ - unsigned int i, ctl; - unsigned long long pci_base, pci_bound, vme_offset; - struct ca91cx42_driver *bridge; - - bridge = image->parent->driver_priv; - - i = image->number; - - ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); - - pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]); - vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]); - pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]); - - *vme_base = pci_base + vme_offset; - *size = (unsigned long long)(pci_bound - pci_base); - - *enabled = 0; - *aspace = 0; - *cycle = 0; - *dwidth = 0; - - if (ctl & CA91CX42_LSI_CTL_EN) - *enabled = 1; - - /* Setup address space */ - switch (ctl & CA91CX42_LSI_CTL_VAS_M) { - case CA91CX42_LSI_CTL_VAS_A16: - *aspace = VME_A16; - break; - case CA91CX42_LSI_CTL_VAS_A24: - *aspace = VME_A24; - break; - case CA91CX42_LSI_CTL_VAS_A32: - *aspace = VME_A32; - break; - case CA91CX42_LSI_CTL_VAS_CRCSR: - *aspace = VME_CRCSR; - break; - case CA91CX42_LSI_CTL_VAS_USER1: - *aspace = VME_USER1; - break; - case CA91CX42_LSI_CTL_VAS_USER2: - *aspace = VME_USER2; - break; - } - - /* XXX Not sure howto check for MBLT */ - /* Setup cycle types */ - if (ctl & CA91CX42_LSI_CTL_VCT_BLT) - *cycle |= VME_BLT; - else - *cycle |= VME_SCT; - - if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) - *cycle |= VME_SUPER; - else - *cycle |= VME_USER; - - if (ctl & CA91CX42_LSI_CTL_PGM_PGM) - *cycle = VME_PROG; - else - *cycle = VME_DATA; - - /* Setup data width */ - switch (ctl & CA91CX42_LSI_CTL_VDW_M) { - case CA91CX42_LSI_CTL_VDW_D8: - *dwidth = VME_D8; - break; - case CA91CX42_LSI_CTL_VDW_D16: - *dwidth = VME_D16; - break; - case CA91CX42_LSI_CTL_VDW_D32: - *dwidth = VME_D32; - break; - case CA91CX42_LSI_CTL_VDW_D64: - *dwidth = VME_D64; - break; - } - - return 0; -} - -static int ca91cx42_master_get(struct vme_master_resource *image, int *enabled, - unsigned long long *vme_base, unsigned long long *size, u32 *aspace, - u32 *cycle, u32 *dwidth) -{ - int retval; - - spin_lock(&image->lock); - - retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, - cycle, dwidth); - - spin_unlock(&image->lock); - - return retval; -} - -static ssize_t ca91cx42_master_read(struct vme_master_resource *image, - void *buf, size_t count, loff_t offset) -{ - ssize_t retval; - void *addr = image->kern_base + offset; - unsigned int done = 0; - unsigned int count32; - - if (count == 0) - return 0; - - spin_lock(&image->lock); - - /* The following code handles VME address alignment problem - * in order to assure the maximal data width cycle. - * We cannot use memcpy_xxx directly here because it - * may cut data transfer in 8-bits cycles, thus making - * D16 cycle impossible. - * From the other hand, the bridge itself assures that - * maximal configured data cycle is used and splits it - * automatically for non-aligned addresses. - */ - if ((uintptr_t)addr & 0x1) { - *(u8 *)buf = ioread8(addr); - done += 1; - if (done == count) - goto out; - } - if ((uintptr_t)addr & 0x2) { - if ((count - done) < 2) { - *(u8 *)(buf + done) = ioread8(addr + done); - done += 1; - goto out; - } else { - *(u16 *)(buf + done) = ioread16(addr + done); - done += 2; - } - } - - count32 = (count - done) & ~0x3; - if (count32 > 0) { - memcpy_fromio(buf + done, addr + done, (unsigned int)count); - done += count32; - } - - if ((count - done) & 0x2) { - *(u16 *)(buf + done) = ioread16(addr + done); - done += 2; - } - if ((count - done) & 0x1) { - *(u8 *)(buf + done) = ioread8(addr + done); - done += 1; - } -out: - retval = count; - spin_unlock(&image->lock); - - return retval; -} - -static ssize_t ca91cx42_master_write(struct vme_master_resource *image, - void *buf, size_t count, loff_t offset) -{ - ssize_t retval; - void *addr = image->kern_base + offset; - unsigned int done = 0; - unsigned int count32; - - if (count == 0) - return 0; - - spin_lock(&image->lock); - - /* Here we apply for the same strategy we do in master_read - * function in order to assure D16 cycle when required. - */ - if ((uintptr_t)addr & 0x1) { - iowrite8(*(u8 *)buf, addr); - done += 1; - if (done == count) - goto out; - } - if ((uintptr_t)addr & 0x2) { - if ((count - done) < 2) { - iowrite8(*(u8 *)(buf + done), addr + done); - done += 1; - goto out; - } else { - iowrite16(*(u16 *)(buf + done), addr + done); - done += 2; - } - } - - count32 = (count - done) & ~0x3; - if (count32 > 0) { - memcpy_toio(addr + done, buf + done, count32); - done += count32; - } - - if ((count - done) & 0x2) { - iowrite16(*(u16 *)(buf + done), addr + done); - done += 2; - } - if ((count - done) & 0x1) { - iowrite8(*(u8 *)(buf + done), addr + done); - done += 1; - } -out: - retval = count; - - spin_unlock(&image->lock); - - return retval; -} - -static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, - unsigned int mask, unsigned int compare, unsigned int swap, - loff_t offset) -{ - u32 result; - uintptr_t pci_addr; - int i; - struct ca91cx42_driver *bridge; - struct device *dev; - - bridge = image->parent->driver_priv; - dev = image->parent->parent; - - /* Find the PCI address that maps to the desired VME address */ - i = image->number; - - /* Locking as we can only do one of these at a time */ - mutex_lock(&bridge->vme_rmw); - - /* Lock image */ - spin_lock(&image->lock); - - pci_addr = (uintptr_t)image->kern_base + offset; - - /* Address must be 4-byte aligned */ - if (pci_addr & 0x3) { - dev_err(dev, "RMW Address not 4-byte aligned\n"); - result = -EINVAL; - goto out; - } - - /* Ensure RMW Disabled whilst configuring */ - iowrite32(0, bridge->base + SCYC_CTL); - - /* Configure registers */ - iowrite32(mask, bridge->base + SCYC_EN); - iowrite32(compare, bridge->base + SCYC_CMP); - iowrite32(swap, bridge->base + SCYC_SWP); - iowrite32(pci_addr, bridge->base + SCYC_ADDR); - - /* Enable RMW */ - iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL); - - /* Kick process off with a read to the required address. */ - result = ioread32(image->kern_base + offset); - - /* Disable RMW */ - iowrite32(0, bridge->base + SCYC_CTL); - -out: - spin_unlock(&image->lock); - - mutex_unlock(&bridge->vme_rmw); - - return result; -} - -static int ca91cx42_dma_list_add(struct vme_dma_list *list, - struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count) -{ - struct ca91cx42_dma_entry *entry, *prev; - struct vme_dma_pci *pci_attr; - struct vme_dma_vme *vme_attr; - dma_addr_t desc_ptr; - int retval = 0; - struct device *dev; - - dev = list->parent->parent->parent; - - /* XXX descriptor must be aligned on 64-bit boundaries */ - entry = kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL); - if (entry == NULL) { - dev_err(dev, "Failed to allocate memory for dma resource " - "structure\n"); - retval = -ENOMEM; - goto err_mem; - } - - /* Test descriptor alignment */ - if ((unsigned long)&entry->descriptor & CA91CX42_DCPP_M) { - dev_err(dev, "Descriptor not aligned to 16 byte boundary as " - "required: %p\n", &entry->descriptor); - retval = -EINVAL; - goto err_align; - } - - memset(&entry->descriptor, 0, sizeof(struct ca91cx42_dma_descriptor)); - - if (dest->type == VME_DMA_VME) { - entry->descriptor.dctl |= CA91CX42_DCTL_L2V; - vme_attr = dest->private; - pci_attr = src->private; - } else { - vme_attr = src->private; - pci_attr = dest->private; - } - - /* Check we can do fulfill required attributes */ - if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 | - VME_USER2)) != 0) { - - dev_err(dev, "Unsupported cycle type\n"); - retval = -EINVAL; - goto err_aspace; - } - - if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER | - VME_PROG | VME_DATA)) != 0) { - - dev_err(dev, "Unsupported cycle type\n"); - retval = -EINVAL; - goto err_cycle; - } - - /* Check to see if we can fulfill source and destination */ - if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) || - ((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) { - - dev_err(dev, "Cannot perform transfer with this " - "source-destination combination\n"); - retval = -EINVAL; - goto err_direct; - } - - /* Setup cycle types */ - if (vme_attr->cycle & VME_BLT) - entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT; - - /* Setup data width */ - switch (vme_attr->dwidth) { - case VME_D8: - entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8; - break; - case VME_D16: - entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16; - break; - case VME_D32: - entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32; - break; - case VME_D64: - entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64; - break; - default: - dev_err(dev, "Invalid data width\n"); - return -EINVAL; - } - - /* Setup address space */ - switch (vme_attr->aspace) { - case VME_A16: - entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16; - break; - case VME_A24: - entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24; - break; - case VME_A32: - entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32; - break; - case VME_USER1: - entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1; - break; - case VME_USER2: - entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2; - break; - default: - dev_err(dev, "Invalid address space\n"); - return -EINVAL; - break; - } - - if (vme_attr->cycle & VME_SUPER) - entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR; - if (vme_attr->cycle & VME_PROG) - entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM; - - entry->descriptor.dtbc = count; - entry->descriptor.dla = pci_attr->address; - entry->descriptor.dva = vme_attr->address; - entry->descriptor.dcpp = CA91CX42_DCPP_NULL; - - /* Add to list */ - list_add_tail(&entry->list, &list->entries); - - /* Fill out previous descriptors "Next Address" */ - if (entry->list.prev != &list->entries) { - prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry, - list); - /* We need the bus address for the pointer */ - desc_ptr = virt_to_bus(&entry->descriptor); - prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M; - } - - return 0; - -err_cycle: -err_aspace: -err_direct: -err_align: - kfree(entry); -err_mem: - return retval; -} - -static int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge) -{ - u32 tmp; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - tmp = ioread32(bridge->base + DGCS); - - if (tmp & CA91CX42_DGCS_ACT) - return 0; - else - return 1; -} - -static int ca91cx42_dma_list_exec(struct vme_dma_list *list) -{ - struct vme_dma_resource *ctrlr; - struct ca91cx42_dma_entry *entry; - int retval = 0; - dma_addr_t bus_addr; - u32 val; - struct device *dev; - struct ca91cx42_driver *bridge; - - ctrlr = list->parent; - - bridge = ctrlr->parent->driver_priv; - dev = ctrlr->parent->parent; - - mutex_lock(&ctrlr->mtx); - - if (!(list_empty(&ctrlr->running))) { - /* - * XXX We have an active DMA transfer and currently haven't - * sorted out the mechanism for "pending" DMA transfers. - * Return busy. - */ - /* Need to add to pending here */ - mutex_unlock(&ctrlr->mtx); - return -EBUSY; - } else { - list_add(&list->list, &ctrlr->running); - } - - /* Get first bus address and write into registers */ - entry = list_first_entry(&list->entries, struct ca91cx42_dma_entry, - list); - - bus_addr = virt_to_bus(&entry->descriptor); - - mutex_unlock(&ctrlr->mtx); - - iowrite32(0, bridge->base + DTBC); - iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP); - - /* Start the operation */ - val = ioread32(bridge->base + DGCS); - - /* XXX Could set VMEbus On and Off Counters here */ - val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M); - - val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT | - CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | - CA91CX42_DGCS_PERR); - - iowrite32(val, bridge->base + DGCS); - - val |= CA91CX42_DGCS_GO; - - iowrite32(val, bridge->base + DGCS); - - wait_event_interruptible(bridge->dma_queue, - ca91cx42_dma_busy(ctrlr->parent)); - - /* - * Read status register, this register is valid until we kick off a - * new transfer. - */ - val = ioread32(bridge->base + DGCS); - - if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | - CA91CX42_DGCS_PERR)) { - - dev_err(dev, "ca91c042: DMA Error. DGCS=%08X\n", val); - val = ioread32(bridge->base + DCTL); - } - - /* Remove list from running list */ - mutex_lock(&ctrlr->mtx); - list_del(&list->list); - mutex_unlock(&ctrlr->mtx); - - return retval; - -} - -static int ca91cx42_dma_list_empty(struct vme_dma_list *list) -{ - struct list_head *pos, *temp; - struct ca91cx42_dma_entry *entry; - - /* detach and free each entry */ - list_for_each_safe(pos, temp, &list->entries) { - list_del(pos); - entry = list_entry(pos, struct ca91cx42_dma_entry, list); - kfree(entry); - } - - return 0; -} - -/* - * All 4 location monitors reside at the same base - this is therefore a - * system wide configuration. - * - * This does not enable the LM monitor - that should be done when the first - * callback is attached and disabled when the last callback is removed. - */ -static int ca91cx42_lm_set(struct vme_lm_resource *lm, - unsigned long long lm_base, u32 aspace, u32 cycle) -{ - u32 temp_base, lm_ctl = 0; - int i; - struct ca91cx42_driver *bridge; - struct device *dev; - - bridge = lm->parent->driver_priv; - dev = lm->parent->parent; - - /* Check the alignment of the location monitor */ - temp_base = (u32)lm_base; - if (temp_base & 0xffff) { - dev_err(dev, "Location monitor must be aligned to 64KB " - "boundary"); - return -EINVAL; - } - - mutex_lock(&lm->mtx); - - /* If we already have a callback attached, we can't move it! */ - for (i = 0; i < lm->monitors; i++) { - if (bridge->lm_callback[i] != NULL) { - mutex_unlock(&lm->mtx); - dev_err(dev, "Location monitor callback attached, " - "can't reset\n"); - return -EBUSY; - } - } - - switch (aspace) { - case VME_A16: - lm_ctl |= CA91CX42_LM_CTL_AS_A16; - break; - case VME_A24: - lm_ctl |= CA91CX42_LM_CTL_AS_A24; - break; - case VME_A32: - lm_ctl |= CA91CX42_LM_CTL_AS_A32; - break; - default: - mutex_unlock(&lm->mtx); - dev_err(dev, "Invalid address space\n"); - return -EINVAL; - break; - } - - if (cycle & VME_SUPER) - lm_ctl |= CA91CX42_LM_CTL_SUPR; - if (cycle & VME_USER) - lm_ctl |= CA91CX42_LM_CTL_NPRIV; - if (cycle & VME_PROG) - lm_ctl |= CA91CX42_LM_CTL_PGM; - if (cycle & VME_DATA) - lm_ctl |= CA91CX42_LM_CTL_DATA; - - iowrite32(lm_base, bridge->base + LM_BS); - iowrite32(lm_ctl, bridge->base + LM_CTL); - - mutex_unlock(&lm->mtx); - - return 0; -} - -/* Get configuration of the callback monitor and return whether it is enabled - * or disabled. - */ -static int ca91cx42_lm_get(struct vme_lm_resource *lm, - unsigned long long *lm_base, u32 *aspace, u32 *cycle) -{ - u32 lm_ctl, enabled = 0; - struct ca91cx42_driver *bridge; - - bridge = lm->parent->driver_priv; - - mutex_lock(&lm->mtx); - - *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); - lm_ctl = ioread32(bridge->base + LM_CTL); - - if (lm_ctl & CA91CX42_LM_CTL_EN) - enabled = 1; - - if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) - *aspace = VME_A16; - if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) - *aspace = VME_A24; - if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) - *aspace = VME_A32; - - *cycle = 0; - if (lm_ctl & CA91CX42_LM_CTL_SUPR) - *cycle |= VME_SUPER; - if (lm_ctl & CA91CX42_LM_CTL_NPRIV) - *cycle |= VME_USER; - if (lm_ctl & CA91CX42_LM_CTL_PGM) - *cycle |= VME_PROG; - if (lm_ctl & CA91CX42_LM_CTL_DATA) - *cycle |= VME_DATA; - - mutex_unlock(&lm->mtx); - - return enabled; -} - -/* - * Attach a callback to a specific location monitor. - * - * Callback will be passed the monitor triggered. - */ -static int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, - void (*callback)(int)) -{ - u32 lm_ctl, tmp; - struct ca91cx42_driver *bridge; - struct device *dev; - - bridge = lm->parent->driver_priv; - dev = lm->parent->parent; - - mutex_lock(&lm->mtx); - - /* Ensure that the location monitor is configured - need PGM or DATA */ - lm_ctl = ioread32(bridge->base + LM_CTL); - if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { - mutex_unlock(&lm->mtx); - dev_err(dev, "Location monitor not properly configured\n"); - return -EINVAL; - } - - /* Check that a callback isn't already attached */ - if (bridge->lm_callback[monitor] != NULL) { - mutex_unlock(&lm->mtx); - dev_err(dev, "Existing callback attached\n"); - return -EBUSY; - } - - /* Attach callback */ - bridge->lm_callback[monitor] = callback; - - /* Enable Location Monitor interrupt */ - tmp = ioread32(bridge->base + LINT_EN); - tmp |= CA91CX42_LINT_LM[monitor]; - iowrite32(tmp, bridge->base + LINT_EN); - - /* Ensure that global Location Monitor Enable set */ - if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { - lm_ctl |= CA91CX42_LM_CTL_EN; - iowrite32(lm_ctl, bridge->base + LM_CTL); - } - - mutex_unlock(&lm->mtx); - - return 0; -} - -/* - * Detach a callback function forn a specific location monitor. - */ -static int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) -{ - u32 tmp; - struct ca91cx42_driver *bridge; - - bridge = lm->parent->driver_priv; - - mutex_lock(&lm->mtx); - - /* Disable Location Monitor and ensure previous interrupts are clear */ - tmp = ioread32(bridge->base + LINT_EN); - tmp &= ~CA91CX42_LINT_LM[monitor]; - iowrite32(tmp, bridge->base + LINT_EN); - - iowrite32(CA91CX42_LINT_LM[monitor], - bridge->base + LINT_STAT); - - /* Detach callback */ - bridge->lm_callback[monitor] = NULL; - - /* If all location monitors disabled, disable global Location Monitor */ - if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | - CA91CX42_LINT_LM3)) == 0) { - tmp = ioread32(bridge->base + LM_CTL); - tmp &= ~CA91CX42_LM_CTL_EN; - iowrite32(tmp, bridge->base + LM_CTL); - } - - mutex_unlock(&lm->mtx); - - return 0; -} - -static int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) -{ - u32 slot = 0; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - if (!geoid) { - slot = ioread32(bridge->base + VCSR_BS); - slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); - } else - slot = geoid; - - return (int)slot; - -} - -void *ca91cx42_alloc_consistent(struct device *parent, size_t size, - dma_addr_t *dma) -{ - struct pci_dev *pdev; - - /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); - - return pci_alloc_consistent(pdev, size, dma); -} - -void ca91cx42_free_consistent(struct device *parent, size_t size, void *vaddr, - dma_addr_t dma) -{ - struct pci_dev *pdev; - - /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); - - pci_free_consistent(pdev, size, vaddr, dma); -} - -static int __init ca91cx42_init(void) -{ - return pci_register_driver(&ca91cx42_driver); -} - -/* - * Configure CR/CSR space - * - * Access to the CR/CSR can be configured at power-up. The location of the - * CR/CSR registers in the CR/CSR address space is determined by the boards - * Auto-ID or Geographic address. This function ensures that the window is - * enabled at an offset consistent with the boards geopgraphic address. - */ -static int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, - struct pci_dev *pdev) -{ - unsigned int crcsr_addr; - int tmp, slot; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - slot = ca91cx42_slot_get(ca91cx42_bridge); - - /* Write CSR Base Address if slot ID is supplied as a module param */ - if (geoid) - iowrite32(geoid << 27, bridge->base + VCSR_BS); - - dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); - if (slot == 0) { - dev_err(&pdev->dev, "Slot number is unset, not configuring " - "CR/CSR space\n"); - return -EINVAL; - } - - /* Allocate mem for CR/CSR image */ - bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, - &bridge->crcsr_bus); - if (bridge->crcsr_kernel == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " - "image\n"); - return -ENOMEM; - } - - memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); - - crcsr_addr = slot * (512 * 1024); - iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); - - tmp = ioread32(bridge->base + VCSR_CTL); - tmp |= CA91CX42_VCSR_CTL_EN; - iowrite32(tmp, bridge->base + VCSR_CTL); - - return 0; -} - -static void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge, - struct pci_dev *pdev) -{ - u32 tmp; - struct ca91cx42_driver *bridge; - - bridge = ca91cx42_bridge->driver_priv; - - /* Turn off CR/CSR space */ - tmp = ioread32(bridge->base + VCSR_CTL); - tmp &= ~CA91CX42_VCSR_CTL_EN; - iowrite32(tmp, bridge->base + VCSR_CTL); - - /* Free image */ - iowrite32(0, bridge->base + VCSR_TO); - - pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, - bridge->crcsr_bus); -} - -static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int retval, i; - u32 data; - struct list_head *pos = NULL; - struct vme_bridge *ca91cx42_bridge; - struct ca91cx42_driver *ca91cx42_device; - struct vme_master_resource *master_image; - struct vme_slave_resource *slave_image; - struct vme_dma_resource *dma_ctrlr; - struct vme_lm_resource *lm; - - /* We want to support more than one of each bridge so we need to - * dynamically allocate the bridge structure - */ - ca91cx42_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); - - if (ca91cx42_bridge == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for device " - "structure\n"); - retval = -ENOMEM; - goto err_struct; - } - - ca91cx42_device = kzalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL); - - if (ca91cx42_device == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for device " - "structure\n"); - retval = -ENOMEM; - goto err_driver; - } - - ca91cx42_bridge->driver_priv = ca91cx42_device; - - /* Enable the device */ - retval = pci_enable_device(pdev); - if (retval) { - dev_err(&pdev->dev, "Unable to enable device\n"); - goto err_enable; - } - - /* Map Registers */ - retval = pci_request_regions(pdev, driver_name); - if (retval) { - dev_err(&pdev->dev, "Unable to reserve resources\n"); - goto err_resource; - } - - /* map registers in BAR 0 */ - ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0), - 4096); - if (!ca91cx42_device->base) { - dev_err(&pdev->dev, "Unable to remap CRG region\n"); - retval = -EIO; - goto err_remap; - } - - /* Check to see if the mapping worked out */ - data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF; - if (data != PCI_VENDOR_ID_TUNDRA) { - dev_err(&pdev->dev, "PCI_ID check failed\n"); - retval = -EIO; - goto err_test; - } - - /* Initialize wait queues & mutual exclusion flags */ - init_waitqueue_head(&ca91cx42_device->dma_queue); - init_waitqueue_head(&ca91cx42_device->iack_queue); - mutex_init(&ca91cx42_device->vme_int); - mutex_init(&ca91cx42_device->vme_rmw); - - ca91cx42_bridge->parent = &pdev->dev; - strcpy(ca91cx42_bridge->name, driver_name); - - /* Setup IRQ */ - retval = ca91cx42_irq_init(ca91cx42_bridge); - if (retval != 0) { - dev_err(&pdev->dev, "Chip Initialization failed.\n"); - goto err_irq; - } - - /* Add master windows to list */ - INIT_LIST_HEAD(&ca91cx42_bridge->master_resources); - for (i = 0; i < CA91C142_MAX_MASTER; i++) { - master_image = kmalloc(sizeof(struct vme_master_resource), - GFP_KERNEL); - if (master_image == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "master resource structure\n"); - retval = -ENOMEM; - goto err_master; - } - master_image->parent = ca91cx42_bridge; - spin_lock_init(&master_image->lock); - master_image->locked = 0; - master_image->number = i; - master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | - VME_CRCSR | VME_USER1 | VME_USER2; - master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | - VME_SUPER | VME_USER | VME_PROG | VME_DATA; - master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; - memset(&master_image->bus_resource, 0, - sizeof(struct resource)); - master_image->kern_base = NULL; - list_add_tail(&master_image->list, - &ca91cx42_bridge->master_resources); - } - - /* Add slave windows to list */ - INIT_LIST_HEAD(&ca91cx42_bridge->slave_resources); - for (i = 0; i < CA91C142_MAX_SLAVE; i++) { - slave_image = kmalloc(sizeof(struct vme_slave_resource), - GFP_KERNEL); - if (slave_image == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "slave resource structure\n"); - retval = -ENOMEM; - goto err_slave; - } - slave_image->parent = ca91cx42_bridge; - mutex_init(&slave_image->mtx); - slave_image->locked = 0; - slave_image->number = i; - slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | - VME_USER2; - - /* Only windows 0 and 4 support A16 */ - if (i == 0 || i == 4) - slave_image->address_attr |= VME_A16; - - slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | - VME_SUPER | VME_USER | VME_PROG | VME_DATA; - list_add_tail(&slave_image->list, - &ca91cx42_bridge->slave_resources); - } - - /* Add dma engines to list */ - INIT_LIST_HEAD(&ca91cx42_bridge->dma_resources); - for (i = 0; i < CA91C142_MAX_DMA; i++) { - dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), - GFP_KERNEL); - if (dma_ctrlr == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "dma resource structure\n"); - retval = -ENOMEM; - goto err_dma; - } - dma_ctrlr->parent = ca91cx42_bridge; - mutex_init(&dma_ctrlr->mtx); - dma_ctrlr->locked = 0; - dma_ctrlr->number = i; - dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | - VME_DMA_MEM_TO_VME; - INIT_LIST_HEAD(&dma_ctrlr->pending); - INIT_LIST_HEAD(&dma_ctrlr->running); - list_add_tail(&dma_ctrlr->list, - &ca91cx42_bridge->dma_resources); - } - - /* Add location monitor to list */ - INIT_LIST_HEAD(&ca91cx42_bridge->lm_resources); - lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); - if (lm == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "location monitor resource structure\n"); - retval = -ENOMEM; - goto err_lm; - } - lm->parent = ca91cx42_bridge; - mutex_init(&lm->mtx); - lm->locked = 0; - lm->number = 1; - lm->monitors = 4; - list_add_tail(&lm->list, &ca91cx42_bridge->lm_resources); - - ca91cx42_bridge->slave_get = ca91cx42_slave_get; - ca91cx42_bridge->slave_set = ca91cx42_slave_set; - ca91cx42_bridge->master_get = ca91cx42_master_get; - ca91cx42_bridge->master_set = ca91cx42_master_set; - ca91cx42_bridge->master_read = ca91cx42_master_read; - ca91cx42_bridge->master_write = ca91cx42_master_write; - ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; - ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; - ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; - ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; - ca91cx42_bridge->irq_set = ca91cx42_irq_set; - ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; - ca91cx42_bridge->lm_set = ca91cx42_lm_set; - ca91cx42_bridge->lm_get = ca91cx42_lm_get; - ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; - ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; - ca91cx42_bridge->slot_get = ca91cx42_slot_get; - ca91cx42_bridge->alloc_consistent = ca91cx42_alloc_consistent; - ca91cx42_bridge->free_consistent = ca91cx42_free_consistent; - - data = ioread32(ca91cx42_device->base + MISC_CTL); - dev_info(&pdev->dev, "Board is%s the VME system controller\n", - (data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); - dev_info(&pdev->dev, "Slot ID is %d\n", - ca91cx42_slot_get(ca91cx42_bridge)); - - if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) - dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); - - /* Need to save ca91cx42_bridge pointer locally in link list for use in - * ca91cx42_remove() - */ - retval = vme_register_bridge(ca91cx42_bridge); - if (retval != 0) { - dev_err(&pdev->dev, "Chip Registration failed.\n"); - goto err_reg; - } - - pci_set_drvdata(pdev, ca91cx42_bridge); - - return 0; - -err_reg: - ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); -err_lm: - /* resources are stored in link list */ - list_for_each(pos, &ca91cx42_bridge->lm_resources) { - lm = list_entry(pos, struct vme_lm_resource, list); - list_del(pos); - kfree(lm); - } -err_dma: - /* resources are stored in link list */ - list_for_each(pos, &ca91cx42_bridge->dma_resources) { - dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); - list_del(pos); - kfree(dma_ctrlr); - } -err_slave: - /* resources are stored in link list */ - list_for_each(pos, &ca91cx42_bridge->slave_resources) { - slave_image = list_entry(pos, struct vme_slave_resource, list); - list_del(pos); - kfree(slave_image); - } -err_master: - /* resources are stored in link list */ - list_for_each(pos, &ca91cx42_bridge->master_resources) { - master_image = list_entry(pos, struct vme_master_resource, - list); - list_del(pos); - kfree(master_image); - } - - ca91cx42_irq_exit(ca91cx42_device, pdev); -err_irq: -err_test: - iounmap(ca91cx42_device->base); -err_remap: - pci_release_regions(pdev); -err_resource: - pci_disable_device(pdev); -err_enable: - kfree(ca91cx42_device); -err_driver: - kfree(ca91cx42_bridge); -err_struct: - return retval; - -} - -static void ca91cx42_remove(struct pci_dev *pdev) -{ - struct list_head *pos = NULL; - struct vme_master_resource *master_image; - struct vme_slave_resource *slave_image; - struct vme_dma_resource *dma_ctrlr; - struct vme_lm_resource *lm; - struct ca91cx42_driver *bridge; - struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev); - - bridge = ca91cx42_bridge->driver_priv; - - - /* Turn off Ints */ - iowrite32(0, bridge->base + LINT_EN); - - /* Turn off the windows */ - iowrite32(0x00800000, bridge->base + LSI0_CTL); - iowrite32(0x00800000, bridge->base + LSI1_CTL); - iowrite32(0x00800000, bridge->base + LSI2_CTL); - iowrite32(0x00800000, bridge->base + LSI3_CTL); - iowrite32(0x00800000, bridge->base + LSI4_CTL); - iowrite32(0x00800000, bridge->base + LSI5_CTL); - iowrite32(0x00800000, bridge->base + LSI6_CTL); - iowrite32(0x00800000, bridge->base + LSI7_CTL); - iowrite32(0x00F00000, bridge->base + VSI0_CTL); - iowrite32(0x00F00000, bridge->base + VSI1_CTL); - iowrite32(0x00F00000, bridge->base + VSI2_CTL); - iowrite32(0x00F00000, bridge->base + VSI3_CTL); - iowrite32(0x00F00000, bridge->base + VSI4_CTL); - iowrite32(0x00F00000, bridge->base + VSI5_CTL); - iowrite32(0x00F00000, bridge->base + VSI6_CTL); - iowrite32(0x00F00000, bridge->base + VSI7_CTL); - - vme_unregister_bridge(ca91cx42_bridge); - - ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); - - /* resources are stored in link list */ - list_for_each(pos, &ca91cx42_bridge->lm_resources) { - lm = list_entry(pos, struct vme_lm_resource, list); - list_del(pos); - kfree(lm); - } - - /* resources are stored in link list */ - list_for_each(pos, &ca91cx42_bridge->dma_resources) { - dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); - list_del(pos); - kfree(dma_ctrlr); - } - - /* resources are stored in link list */ - list_for_each(pos, &ca91cx42_bridge->slave_resources) { - slave_image = list_entry(pos, struct vme_slave_resource, list); - list_del(pos); - kfree(slave_image); - } - - /* resources are stored in link list */ - list_for_each(pos, &ca91cx42_bridge->master_resources) { - master_image = list_entry(pos, struct vme_master_resource, - list); - list_del(pos); - kfree(master_image); - } - - ca91cx42_irq_exit(bridge, pdev); - - iounmap(bridge->base); - - pci_release_regions(pdev); - - pci_disable_device(pdev); - - kfree(ca91cx42_bridge); -} - -static void __exit ca91cx42_exit(void) -{ - pci_unregister_driver(&ca91cx42_driver); -} - -MODULE_PARM_DESC(geoid, "Override geographical addressing"); -module_param(geoid, int, 0); - -MODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); -MODULE_LICENSE("GPL"); - -module_init(ca91cx42_init); -module_exit(ca91cx42_exit); diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/staging/vme/bridges/vme_ca91cx42.h deleted file mode 100644 index 02a7c794db05..000000000000 --- a/drivers/staging/vme/bridges/vme_ca91cx42.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - * ca91c042.h - * - * Support for the Tundra Universe 1 and Universe II VME bridge chips - * - * Author: Tom Armistead - * Updated by Ajit Prem - * Copyright 2004 Motorola Inc. - * - * Further updated by Martyn Welch - * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. - * - * Derived from ca91c042.h by Michael Wyrick - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef _CA91CX42_H -#define _CA91CX42_H - -#ifndef PCI_VENDOR_ID_TUNDRA -#define PCI_VENDOR_ID_TUNDRA 0x10e3 -#endif - -#ifndef PCI_DEVICE_ID_TUNDRA_CA91C142 -#define PCI_DEVICE_ID_TUNDRA_CA91C142 0x0000 -#endif - -/* - * Define the number of each that the CA91C142 supports. - */ -#define CA91C142_MAX_MASTER 8 /* Max Master Windows */ -#define CA91C142_MAX_SLAVE 8 /* Max Slave Windows */ -#define CA91C142_MAX_DMA 1 /* Max DMA Controllers */ -#define CA91C142_MAX_MAILBOX 4 /* Max Mail Box registers */ - -/* Structure used to hold driver specific information */ -struct ca91cx42_driver { - void __iomem *base; /* Base Address of device registers */ - wait_queue_head_t dma_queue; - wait_queue_head_t iack_queue; - wait_queue_head_t mbox_queue; - void (*lm_callback[4])(int); /* Called in interrupt handler */ - void *crcsr_kernel; - dma_addr_t crcsr_bus; - struct mutex vme_rmw; /* Only one RMW cycle at a time */ - struct mutex vme_int; /* - * Only one VME interrupt can be - * generated at a time, provide locking - */ -}; - -/* See Page 2-77 in the Universe User Manual */ -struct ca91cx42_dma_descriptor { - unsigned int dctl; /* DMA Control */ - unsigned int dtbc; /* Transfer Byte Count */ - unsigned int dla; /* PCI Address */ - unsigned int res1; /* Reserved */ - unsigned int dva; /* Vme Address */ - unsigned int res2; /* Reserved */ - unsigned int dcpp; /* Pointer to Numed Cmd Packet with rPN */ - unsigned int res3; /* Reserved */ -}; - -struct ca91cx42_dma_entry { - struct ca91cx42_dma_descriptor descriptor; - struct list_head list; -}; - -/* Universe Register Offsets */ -/* general PCI configuration registers */ -#define CA91CX42_PCI_ID 0x000 -#define CA91CX42_PCI_CSR 0x004 -#define CA91CX42_PCI_CLASS 0x008 -#define CA91CX42_PCI_MISC0 0x00C -#define CA91CX42_PCI_BS 0x010 -#define CA91CX42_PCI_MISC1 0x03C - -#define LSI0_CTL 0x0100 -#define LSI0_BS 0x0104 -#define LSI0_BD 0x0108 -#define LSI0_TO 0x010C - -#define LSI1_CTL 0x0114 -#define LSI1_BS 0x0118 -#define LSI1_BD 0x011C -#define LSI1_TO 0x0120 - -#define LSI2_CTL 0x0128 -#define LSI2_BS 0x012C -#define LSI2_BD 0x0130 -#define LSI2_TO 0x0134 - -#define LSI3_CTL 0x013C -#define LSI3_BS 0x0140 -#define LSI3_BD 0x0144 -#define LSI3_TO 0x0148 - -#define LSI4_CTL 0x01A0 -#define LSI4_BS 0x01A4 -#define LSI4_BD 0x01A8 -#define LSI4_TO 0x01AC - -#define LSI5_CTL 0x01B4 -#define LSI5_BS 0x01B8 -#define LSI5_BD 0x01BC -#define LSI5_TO 0x01C0 - -#define LSI6_CTL 0x01C8 -#define LSI6_BS 0x01CC -#define LSI6_BD 0x01D0 -#define LSI6_TO 0x01D4 - -#define LSI7_CTL 0x01DC -#define LSI7_BS 0x01E0 -#define LSI7_BD 0x01E4 -#define LSI7_TO 0x01E8 - -static const int CA91CX42_LSI_CTL[] = { LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL, - LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL }; - -static const int CA91CX42_LSI_BS[] = { LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS, - LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS }; - -static const int CA91CX42_LSI_BD[] = { LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD, - LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD }; - -static const int CA91CX42_LSI_TO[] = { LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO, - LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO }; - -#define SCYC_CTL 0x0170 -#define SCYC_ADDR 0x0174 -#define SCYC_EN 0x0178 -#define SCYC_CMP 0x017C -#define SCYC_SWP 0x0180 -#define LMISC 0x0184 -#define SLSI 0x0188 -#define L_CMDERR 0x018C -#define LAERR 0x0190 - -#define DCTL 0x0200 -#define DTBC 0x0204 -#define DLA 0x0208 -#define DVA 0x0210 -#define DCPP 0x0218 -#define DGCS 0x0220 -#define D_LLUE 0x0224 - -#define LINT_EN 0x0300 -#define LINT_STAT 0x0304 -#define LINT_MAP0 0x0308 -#define LINT_MAP1 0x030C -#define VINT_EN 0x0310 -#define VINT_STAT 0x0314 -#define VINT_MAP0 0x0318 -#define VINT_MAP1 0x031C -#define STATID 0x0320 - -#define V1_STATID 0x0324 -#define V2_STATID 0x0328 -#define V3_STATID 0x032C -#define V4_STATID 0x0330 -#define V5_STATID 0x0334 -#define V6_STATID 0x0338 -#define V7_STATID 0x033C - -static const int CA91CX42_V_STATID[8] = { 0, V1_STATID, V2_STATID, V3_STATID, - V4_STATID, V5_STATID, V6_STATID, - V7_STATID }; - -#define LINT_MAP2 0x0340 -#define VINT_MAP2 0x0344 - -#define MBOX0 0x0348 -#define MBOX1 0x034C -#define MBOX2 0x0350 -#define MBOX3 0x0354 -#define SEMA0 0x0358 -#define SEMA1 0x035C - -#define MAST_CTL 0x0400 -#define MISC_CTL 0x0404 -#define MISC_STAT 0x0408 -#define USER_AM 0x040C - -#define VSI0_CTL 0x0F00 -#define VSI0_BS 0x0F04 -#define VSI0_BD 0x0F08 -#define VSI0_TO 0x0F0C - -#define VSI1_CTL 0x0F14 -#define VSI1_BS 0x0F18 -#define VSI1_BD 0x0F1C -#define VSI1_TO 0x0F20 - -#define VSI2_CTL 0x0F28 -#define VSI2_BS 0x0F2C -#define VSI2_BD 0x0F30 -#define VSI2_TO 0x0F34 - -#define VSI3_CTL 0x0F3C -#define VSI3_BS 0x0F40 -#define VSI3_BD 0x0F44 -#define VSI3_TO 0x0F48 - -#define LM_CTL 0x0F64 -#define LM_BS 0x0F68 - -#define VRAI_CTL 0x0F70 - -#define VRAI_BS 0x0F74 -#define VCSR_CTL 0x0F80 -#define VCSR_TO 0x0F84 -#define V_AMERR 0x0F88 -#define VAERR 0x0F8C - -#define VSI4_CTL 0x0F90 -#define VSI4_BS 0x0F94 -#define VSI4_BD 0x0F98 -#define VSI4_TO 0x0F9C - -#define VSI5_CTL 0x0FA4 -#define VSI5_BS 0x0FA8 -#define VSI5_BD 0x0FAC -#define VSI5_TO 0x0FB0 - -#define VSI6_CTL 0x0FB8 -#define VSI6_BS 0x0FBC -#define VSI6_BD 0x0FC0 -#define VSI6_TO 0x0FC4 - -#define VSI7_CTL 0x0FCC -#define VSI7_BS 0x0FD0 -#define VSI7_BD 0x0FD4 -#define VSI7_TO 0x0FD8 - -static const int CA91CX42_VSI_CTL[] = { VSI0_CTL, VSI1_CTL, VSI2_CTL, VSI3_CTL, - VSI4_CTL, VSI5_CTL, VSI6_CTL, VSI7_CTL }; - -static const int CA91CX42_VSI_BS[] = { VSI0_BS, VSI1_BS, VSI2_BS, VSI3_BS, - VSI4_BS, VSI5_BS, VSI6_BS, VSI7_BS }; - -static const int CA91CX42_VSI_BD[] = { VSI0_BD, VSI1_BD, VSI2_BD, VSI3_BD, - VSI4_BD, VSI5_BD, VSI6_BD, VSI7_BD }; - -static const int CA91CX42_VSI_TO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO, - VSI4_TO, VSI5_TO, VSI6_TO, VSI7_TO }; - -#define VCSR_CLR 0x0FF4 -#define VCSR_SET 0x0FF8 -#define VCSR_BS 0x0FFC - -/* - * PCI Class Register - * offset 008 - */ -#define CA91CX42_BM_PCI_CLASS_BASE 0xFF000000 -#define CA91CX42_OF_PCI_CLASS_BASE 24 -#define CA91CX42_BM_PCI_CLASS_SUB 0x00FF0000 -#define CA91CX42_OF_PCI_CLASS_SUB 16 -#define CA91CX42_BM_PCI_CLASS_PROG 0x0000FF00 -#define CA91CX42_OF_PCI_CLASS_PROG 8 -#define CA91CX42_BM_PCI_CLASS_RID 0x000000FF -#define CA91CX42_OF_PCI_CLASS_RID 0 - -#define CA91CX42_OF_PCI_CLASS_RID_UNIVERSE_I 0 -#define CA91CX42_OF_PCI_CLASS_RID_UNIVERSE_II 1 - -/* - * PCI Misc Register - * offset 00C - */ -#define CA91CX42_BM_PCI_MISC0_BISTC 0x80000000 -#define CA91CX42_BM_PCI_MISC0_SBIST 0x60000000 -#define CA91CX42_BM_PCI_MISC0_CCODE 0x0F000000 -#define CA91CX42_BM_PCI_MISC0_MFUNCT 0x00800000 -#define CA91CX42_BM_PCI_MISC0_LAYOUT 0x007F0000 -#define CA91CX42_BM_PCI_MISC0_LTIMER 0x0000FF00 -#define CA91CX42_OF_PCI_MISC0_LTIMER 8 - - -/* - * LSI Control Register - * offset 100 - */ -#define CA91CX42_LSI_CTL_EN (1<<31) -#define CA91CX42_LSI_CTL_PWEN (1<<30) - -#define CA91CX42_LSI_CTL_VDW_M (3<<22) -#define CA91CX42_LSI_CTL_VDW_D8 0 -#define CA91CX42_LSI_CTL_VDW_D16 (1<<22) -#define CA91CX42_LSI_CTL_VDW_D32 (1<<23) -#define CA91CX42_LSI_CTL_VDW_D64 (3<<22) - -#define CA91CX42_LSI_CTL_VAS_M (7<<16) -#define CA91CX42_LSI_CTL_VAS_A16 0 -#define CA91CX42_LSI_CTL_VAS_A24 (1<<16) -#define CA91CX42_LSI_CTL_VAS_A32 (1<<17) -#define CA91CX42_LSI_CTL_VAS_CRCSR (5<<16) -#define CA91CX42_LSI_CTL_VAS_USER1 (3<<17) -#define CA91CX42_LSI_CTL_VAS_USER2 (7<<16) - -#define CA91CX42_LSI_CTL_PGM_M (1<<14) -#define CA91CX42_LSI_CTL_PGM_DATA 0 -#define CA91CX42_LSI_CTL_PGM_PGM (1<<14) - -#define CA91CX42_LSI_CTL_SUPER_M (1<<12) -#define CA91CX42_LSI_CTL_SUPER_NPRIV 0 -#define CA91CX42_LSI_CTL_SUPER_SUPR (1<<12) - -#define CA91CX42_LSI_CTL_VCT_M (1<<8) -#define CA91CX42_LSI_CTL_VCT_BLT (1<<8) -#define CA91CX42_LSI_CTL_VCT_MBLT (1<<8) -#define CA91CX42_LSI_CTL_LAS (1<<0) - -/* - * SCYC_CTL Register - * offset 178 - */ -#define CA91CX42_SCYC_CTL_LAS_PCIMEM 0 -#define CA91CX42_SCYC_CTL_LAS_PCIIO (1<<2) - -#define CA91CX42_SCYC_CTL_CYC_M (3<<0) -#define CA91CX42_SCYC_CTL_CYC_RMW (1<<0) -#define CA91CX42_SCYC_CTL_CYC_ADOH (1<<1) - -/* - * LMISC Register - * offset 184 - */ -#define CA91CX42_BM_LMISC_CRT 0xF0000000 -#define CA91CX42_OF_LMISC_CRT 28 -#define CA91CX42_BM_LMISC_CWT 0x0F000000 -#define CA91CX42_OF_LMISC_CWT 24 - -/* - * SLSI Register - * offset 188 - */ -#define CA91CX42_BM_SLSI_EN 0x80000000 -#define CA91CX42_BM_SLSI_PWEN 0x40000000 -#define CA91CX42_BM_SLSI_VDW 0x00F00000 -#define CA91CX42_OF_SLSI_VDW 20 -#define CA91CX42_BM_SLSI_PGM 0x0000F000 -#define CA91CX42_OF_SLSI_PGM 12 -#define CA91CX42_BM_SLSI_SUPER 0x00000F00 -#define CA91CX42_OF_SLSI_SUPER 8 -#define CA91CX42_BM_SLSI_BS 0x000000F6 -#define CA91CX42_OF_SLSI_BS 2 -#define CA91CX42_BM_SLSI_LAS 0x00000003 -#define CA91CX42_OF_SLSI_LAS 0 -#define CA91CX42_BM_SLSI_RESERVED 0x3F0F0000 - -/* - * DCTL Register - * offset 200 - */ -#define CA91CX42_DCTL_L2V (1<<31) -#define CA91CX42_DCTL_VDW_M (3<<22) -#define CA91CX42_DCTL_VDW_M (3<<22) -#define CA91CX42_DCTL_VDW_D8 0 -#define CA91CX42_DCTL_VDW_D16 (1<<22) -#define CA91CX42_DCTL_VDW_D32 (1<<23) -#define CA91CX42_DCTL_VDW_D64 (3<<22) - -#define CA91CX42_DCTL_VAS_M (7<<16) -#define CA91CX42_DCTL_VAS_A16 0 -#define CA91CX42_DCTL_VAS_A24 (1<<16) -#define CA91CX42_DCTL_VAS_A32 (1<<17) -#define CA91CX42_DCTL_VAS_USER1 (3<<17) -#define CA91CX42_DCTL_VAS_USER2 (7<<16) - -#define CA91CX42_DCTL_PGM_M (1<<14) -#define CA91CX42_DCTL_PGM_DATA 0 -#define CA91CX42_DCTL_PGM_PGM (1<<14) - -#define CA91CX42_DCTL_SUPER_M (1<<12) -#define CA91CX42_DCTL_SUPER_NPRIV 0 -#define CA91CX42_DCTL_SUPER_SUPR (1<<12) - -#define CA91CX42_DCTL_VCT_M (1<<8) -#define CA91CX42_DCTL_VCT_BLT (1<<8) -#define CA91CX42_DCTL_LD64EN (1<<7) - -/* - * DCPP Register - * offset 218 - */ -#define CA91CX42_DCPP_M 0xf -#define CA91CX42_DCPP_NULL (1<<0) - -/* - * DMA General Control/Status Register (DGCS) - * offset 220 - */ -#define CA91CX42_DGCS_GO (1<<31) -#define CA91CX42_DGCS_STOP_REQ (1<<30) -#define CA91CX42_DGCS_HALT_REQ (1<<29) -#define CA91CX42_DGCS_CHAIN (1<<27) - -#define CA91CX42_DGCS_VON_M (7<<20) - -#define CA91CX42_DGCS_VOFF_M (0xf<<16) - -#define CA91CX42_DGCS_ACT (1<<15) -#define CA91CX42_DGCS_STOP (1<<14) -#define CA91CX42_DGCS_HALT (1<<13) -#define CA91CX42_DGCS_DONE (1<<11) -#define CA91CX42_DGCS_LERR (1<<10) -#define CA91CX42_DGCS_VERR (1<<9) -#define CA91CX42_DGCS_PERR (1<<8) -#define CA91CX42_DGCS_INT_STOP (1<<6) -#define CA91CX42_DGCS_INT_HALT (1<<5) -#define CA91CX42_DGCS_INT_DONE (1<<3) -#define CA91CX42_DGCS_INT_LERR (1<<2) -#define CA91CX42_DGCS_INT_VERR (1<<1) -#define CA91CX42_DGCS_INT_PERR (1<<0) - -/* - * PCI Interrupt Enable Register - * offset 300 - */ -#define CA91CX42_LINT_LM3 0x00800000 -#define CA91CX42_LINT_LM2 0x00400000 -#define CA91CX42_LINT_LM1 0x00200000 -#define CA91CX42_LINT_LM0 0x00100000 -#define CA91CX42_LINT_MBOX3 0x00080000 -#define CA91CX42_LINT_MBOX2 0x00040000 -#define CA91CX42_LINT_MBOX1 0x00020000 -#define CA91CX42_LINT_MBOX0 0x00010000 -#define CA91CX42_LINT_ACFAIL 0x00008000 -#define CA91CX42_LINT_SYSFAIL 0x00004000 -#define CA91CX42_LINT_SW_INT 0x00002000 -#define CA91CX42_LINT_SW_IACK 0x00001000 - -#define CA91CX42_LINT_VERR 0x00000400 -#define CA91CX42_LINT_LERR 0x00000200 -#define CA91CX42_LINT_DMA 0x00000100 -#define CA91CX42_LINT_VIRQ7 0x00000080 -#define CA91CX42_LINT_VIRQ6 0x00000040 -#define CA91CX42_LINT_VIRQ5 0x00000020 -#define CA91CX42_LINT_VIRQ4 0x00000010 -#define CA91CX42_LINT_VIRQ3 0x00000008 -#define CA91CX42_LINT_VIRQ2 0x00000004 -#define CA91CX42_LINT_VIRQ1 0x00000002 -#define CA91CX42_LINT_VOWN 0x00000001 - -static const int CA91CX42_LINT_VIRQ[] = { 0, CA91CX42_LINT_VIRQ1, - CA91CX42_LINT_VIRQ2, CA91CX42_LINT_VIRQ3, - CA91CX42_LINT_VIRQ4, CA91CX42_LINT_VIRQ5, - CA91CX42_LINT_VIRQ6, CA91CX42_LINT_VIRQ7 }; - -#define CA91CX42_LINT_MBOX 0x000F0000 - -static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1, - CA91CX42_LINT_LM2, CA91CX42_LINT_LM3 }; - -/* - * MAST_CTL Register - * offset 400 - */ -#define CA91CX42_BM_MAST_CTL_MAXRTRY 0xF0000000 -#define CA91CX42_OF_MAST_CTL_MAXRTRY 28 -#define CA91CX42_BM_MAST_CTL_PWON 0x0F000000 -#define CA91CX42_OF_MAST_CTL_PWON 24 -#define CA91CX42_BM_MAST_CTL_VRL 0x00C00000 -#define CA91CX42_OF_MAST_CTL_VRL 22 -#define CA91CX42_BM_MAST_CTL_VRM 0x00200000 -#define CA91CX42_BM_MAST_CTL_VREL 0x00100000 -#define CA91CX42_BM_MAST_CTL_VOWN 0x00080000 -#define CA91CX42_BM_MAST_CTL_VOWN_ACK 0x00040000 -#define CA91CX42_BM_MAST_CTL_PABS 0x00001000 -#define CA91CX42_BM_MAST_CTL_BUS_NO 0x0000000F -#define CA91CX42_OF_MAST_CTL_BUS_NO 0 - -/* - * MISC_CTL Register - * offset 404 - */ -#define CA91CX42_MISC_CTL_VBTO 0xF0000000 -#define CA91CX42_MISC_CTL_VARB 0x04000000 -#define CA91CX42_MISC_CTL_VARBTO 0x03000000 -#define CA91CX42_MISC_CTL_SW_LRST 0x00800000 -#define CA91CX42_MISC_CTL_SW_SRST 0x00400000 -#define CA91CX42_MISC_CTL_BI 0x00100000 -#define CA91CX42_MISC_CTL_ENGBI 0x00080000 -#define CA91CX42_MISC_CTL_RESCIND 0x00040000 -#define CA91CX42_MISC_CTL_SYSCON 0x00020000 -#define CA91CX42_MISC_CTL_V64AUTO 0x00010000 -#define CA91CX42_MISC_CTL_RESERVED 0x0820FFFF - -#define CA91CX42_OF_MISC_CTL_VARBTO 24 -#define CA91CX42_OF_MISC_CTL_VBTO 28 - -/* - * MISC_STAT Register - * offset 408 - */ -#define CA91CX42_BM_MISC_STAT_ENDIAN 0x80000000 -#define CA91CX42_BM_MISC_STAT_LCLSIZE 0x40000000 -#define CA91CX42_BM_MISC_STAT_DY4AUTO 0x08000000 -#define CA91CX42_BM_MISC_STAT_MYBBSY 0x00200000 -#define CA91CX42_BM_MISC_STAT_DY4DONE 0x00080000 -#define CA91CX42_BM_MISC_STAT_TXFE 0x00040000 -#define CA91CX42_BM_MISC_STAT_RXFE 0x00020000 -#define CA91CX42_BM_MISC_STAT_DY4AUTOID 0x0000FF00 -#define CA91CX42_OF_MISC_STAT_DY4AUTOID 8 - -/* - * VSI Control Register - * offset F00 - */ -#define CA91CX42_VSI_CTL_EN (1<<31) -#define CA91CX42_VSI_CTL_PWEN (1<<30) -#define CA91CX42_VSI_CTL_PREN (1<<29) - -#define CA91CX42_VSI_CTL_PGM_M (3<<22) -#define CA91CX42_VSI_CTL_PGM_DATA (1<<22) -#define CA91CX42_VSI_CTL_PGM_PGM (1<<23) - -#define CA91CX42_VSI_CTL_SUPER_M (3<<20) -#define CA91CX42_VSI_CTL_SUPER_NPRIV (1<<20) -#define CA91CX42_VSI_CTL_SUPER_SUPR (1<<21) - -#define CA91CX42_VSI_CTL_VAS_M (7<<16) -#define CA91CX42_VSI_CTL_VAS_A16 0 -#define CA91CX42_VSI_CTL_VAS_A24 (1<<16) -#define CA91CX42_VSI_CTL_VAS_A32 (1<<17) -#define CA91CX42_VSI_CTL_VAS_USER1 (3<<17) -#define CA91CX42_VSI_CTL_VAS_USER2 (7<<16) - -#define CA91CX42_VSI_CTL_LD64EN (1<<7) -#define CA91CX42_VSI_CTL_LLRMW (1<<6) - -#define CA91CX42_VSI_CTL_LAS_M (3<<0) -#define CA91CX42_VSI_CTL_LAS_PCI_MS 0 -#define CA91CX42_VSI_CTL_LAS_PCI_IO (1<<0) -#define CA91CX42_VSI_CTL_LAS_PCI_CONF (1<<1) - -/* LM_CTL Register - * offset F64 - */ -#define CA91CX42_LM_CTL_EN (1<<31) -#define CA91CX42_LM_CTL_PGM (1<<23) -#define CA91CX42_LM_CTL_DATA (1<<22) -#define CA91CX42_LM_CTL_SUPR (1<<21) -#define CA91CX42_LM_CTL_NPRIV (1<<20) -#define CA91CX42_LM_CTL_AS_M (5<<16) -#define CA91CX42_LM_CTL_AS_A16 0 -#define CA91CX42_LM_CTL_AS_A24 (1<<16) -#define CA91CX42_LM_CTL_AS_A32 (1<<17) - -/* - * VRAI_CTL Register - * offset F70 - */ -#define CA91CX42_BM_VRAI_CTL_EN 0x80000000 -#define CA91CX42_BM_VRAI_CTL_PGM 0x00C00000 -#define CA91CX42_OF_VRAI_CTL_PGM 22 -#define CA91CX42_BM_VRAI_CTL_SUPER 0x00300000 -#define CA91CX42_OF_VRAI_CTL_SUPER 20 -#define CA91CX42_BM_VRAI_CTL_VAS 0x00030000 -#define CA91CX42_OF_VRAI_CTL_VAS 16 - -/* VCSR_CTL Register - * offset F80 - */ -#define CA91CX42_VCSR_CTL_EN (1<<31) - -#define CA91CX42_VCSR_CTL_LAS_M (3<<0) -#define CA91CX42_VCSR_CTL_LAS_PCI_MS 0 -#define CA91CX42_VCSR_CTL_LAS_PCI_IO (1<<0) -#define CA91CX42_VCSR_CTL_LAS_PCI_CONF (1<<1) - -/* VCSR_BS Register - * offset FFC - */ -#define CA91CX42_VCSR_BS_SLOT_M (0x1F<<27) - -#endif /* _CA91CX42_H */ diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c deleted file mode 100644 index ced59421302e..000000000000 --- a/drivers/staging/vme/bridges/vme_tsi148.c +++ /dev/null @@ -1,2691 +0,0 @@ -/* - * Support for the Tundra TSI148 VME-PCI Bridge Chip - * - * Author: Martyn Welch - * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. - * - * Based on work by Tom Armistead and Ajit Prem - * Copyright 2004 Motorola Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../vme.h" -#include "../vme_bridge.h" -#include "vme_tsi148.h" - -static int __init tsi148_init(void); -static int tsi148_probe(struct pci_dev *, const struct pci_device_id *); -static void tsi148_remove(struct pci_dev *); -static void __exit tsi148_exit(void); - - -/* Module parameter */ -static bool err_chk; -static int geoid; - -static const char driver_name[] = "vme_tsi148"; - -static DEFINE_PCI_DEVICE_TABLE(tsi148_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) }, - { }, -}; - -static struct pci_driver tsi148_driver = { - .name = driver_name, - .id_table = tsi148_ids, - .probe = tsi148_probe, - .remove = tsi148_remove, -}; - -static void reg_join(unsigned int high, unsigned int low, - unsigned long long *variable) -{ - *variable = (unsigned long long)high << 32; - *variable |= (unsigned long long)low; -} - -static void reg_split(unsigned long long variable, unsigned int *high, - unsigned int *low) -{ - *low = (unsigned int)variable & 0xFFFFFFFF; - *high = (unsigned int)(variable >> 32); -} - -/* - * Wakes up DMA queue. - */ -static u32 tsi148_DMA_irqhandler(struct tsi148_driver *bridge, - int channel_mask) -{ - u32 serviced = 0; - - if (channel_mask & TSI148_LCSR_INTS_DMA0S) { - wake_up(&bridge->dma_queue[0]); - serviced |= TSI148_LCSR_INTC_DMA0C; - } - if (channel_mask & TSI148_LCSR_INTS_DMA1S) { - wake_up(&bridge->dma_queue[1]); - serviced |= TSI148_LCSR_INTC_DMA1C; - } - - return serviced; -} - -/* - * Wake up location monitor queue - */ -static u32 tsi148_LM_irqhandler(struct tsi148_driver *bridge, u32 stat) -{ - int i; - u32 serviced = 0; - - for (i = 0; i < 4; i++) { - if (stat & TSI148_LCSR_INTS_LMS[i]) { - /* We only enable interrupts if the callback is set */ - bridge->lm_callback[i](i); - serviced |= TSI148_LCSR_INTC_LMC[i]; - } - } - - return serviced; -} - -/* - * Wake up mail box queue. - * - * XXX This functionality is not exposed up though API. - */ -static u32 tsi148_MB_irqhandler(struct vme_bridge *tsi148_bridge, u32 stat) -{ - int i; - u32 val; - u32 serviced = 0; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - for (i = 0; i < 4; i++) { - if (stat & TSI148_LCSR_INTS_MBS[i]) { - val = ioread32be(bridge->base + TSI148_GCSR_MBOX[i]); - dev_err(tsi148_bridge->parent, "VME Mailbox %d received" - ": 0x%x\n", i, val); - serviced |= TSI148_LCSR_INTC_MBC[i]; - } - } - - return serviced; -} - -/* - * Display error & status message when PERR (PCI) exception interrupt occurs. - */ -static u32 tsi148_PERR_irqhandler(struct vme_bridge *tsi148_bridge) -{ - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - dev_err(tsi148_bridge->parent, "PCI Exception at address: 0x%08x:%08x, " - "attributes: %08x\n", - ioread32be(bridge->base + TSI148_LCSR_EDPAU), - ioread32be(bridge->base + TSI148_LCSR_EDPAL), - ioread32be(bridge->base + TSI148_LCSR_EDPAT)); - - dev_err(tsi148_bridge->parent, "PCI-X attribute reg: %08x, PCI-X split " - "completion reg: %08x\n", - ioread32be(bridge->base + TSI148_LCSR_EDPXA), - ioread32be(bridge->base + TSI148_LCSR_EDPXS)); - - iowrite32be(TSI148_LCSR_EDPAT_EDPCL, bridge->base + TSI148_LCSR_EDPAT); - - return TSI148_LCSR_INTC_PERRC; -} - -/* - * Save address and status when VME error interrupt occurs. - */ -static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge) -{ - unsigned int error_addr_high, error_addr_low; - unsigned long long error_addr; - u32 error_attrib; - struct vme_bus_error *error; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU); - error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL); - error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT); - - reg_join(error_addr_high, error_addr_low, &error_addr); - - /* Check for exception register overflow (we have lost error data) */ - if (error_attrib & TSI148_LCSR_VEAT_VEOF) { - dev_err(tsi148_bridge->parent, "VME Bus Exception Overflow " - "Occurred\n"); - } - - error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC); - if (error) { - error->address = error_addr; - error->attributes = error_attrib; - list_add_tail(&error->list, &tsi148_bridge->vme_errors); - } else { - dev_err(tsi148_bridge->parent, "Unable to alloc memory for " - "VMEbus Error reporting\n"); - dev_err(tsi148_bridge->parent, "VME Bus Error at address: " - "0x%llx, attributes: %08x\n", error_addr, error_attrib); - } - - /* Clear Status */ - iowrite32be(TSI148_LCSR_VEAT_VESCL, bridge->base + TSI148_LCSR_VEAT); - - return TSI148_LCSR_INTC_VERRC; -} - -/* - * Wake up IACK queue. - */ -static u32 tsi148_IACK_irqhandler(struct tsi148_driver *bridge) -{ - wake_up(&bridge->iack_queue); - - return TSI148_LCSR_INTC_IACKC; -} - -/* - * Calling VME bus interrupt callback if provided. - */ -static u32 tsi148_VIRQ_irqhandler(struct vme_bridge *tsi148_bridge, - u32 stat) -{ - int vec, i, serviced = 0; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - for (i = 7; i > 0; i--) { - if (stat & (1 << i)) { - /* - * Note: Even though the registers are defined as - * 32-bits in the spec, we only want to issue 8-bit - * IACK cycles on the bus, read from offset 3. - */ - vec = ioread8(bridge->base + TSI148_LCSR_VIACK[i] + 3); - - vme_irq_handler(tsi148_bridge, i, vec); - - serviced |= (1 << i); - } - } - - return serviced; -} - -/* - * Top level interrupt handler. Clears appropriate interrupt status bits and - * then calls appropriate sub handler(s). - */ -static irqreturn_t tsi148_irqhandler(int irq, void *ptr) -{ - u32 stat, enable, serviced = 0; - struct vme_bridge *tsi148_bridge; - struct tsi148_driver *bridge; - - tsi148_bridge = ptr; - - bridge = tsi148_bridge->driver_priv; - - /* Determine which interrupts are unmasked and set */ - enable = ioread32be(bridge->base + TSI148_LCSR_INTEO); - stat = ioread32be(bridge->base + TSI148_LCSR_INTS); - - /* Only look at unmasked interrupts */ - stat &= enable; - - if (unlikely(!stat)) - return IRQ_NONE; - - /* Call subhandlers as appropriate */ - /* DMA irqs */ - if (stat & (TSI148_LCSR_INTS_DMA1S | TSI148_LCSR_INTS_DMA0S)) - serviced |= tsi148_DMA_irqhandler(bridge, stat); - - /* Location monitor irqs */ - if (stat & (TSI148_LCSR_INTS_LM3S | TSI148_LCSR_INTS_LM2S | - TSI148_LCSR_INTS_LM1S | TSI148_LCSR_INTS_LM0S)) - serviced |= tsi148_LM_irqhandler(bridge, stat); - - /* Mail box irqs */ - if (stat & (TSI148_LCSR_INTS_MB3S | TSI148_LCSR_INTS_MB2S | - TSI148_LCSR_INTS_MB1S | TSI148_LCSR_INTS_MB0S)) - serviced |= tsi148_MB_irqhandler(tsi148_bridge, stat); - - /* PCI bus error */ - if (stat & TSI148_LCSR_INTS_PERRS) - serviced |= tsi148_PERR_irqhandler(tsi148_bridge); - - /* VME bus error */ - if (stat & TSI148_LCSR_INTS_VERRS) - serviced |= tsi148_VERR_irqhandler(tsi148_bridge); - - /* IACK irq */ - if (stat & TSI148_LCSR_INTS_IACKS) - serviced |= tsi148_IACK_irqhandler(bridge); - - /* VME bus irqs */ - if (stat & (TSI148_LCSR_INTS_IRQ7S | TSI148_LCSR_INTS_IRQ6S | - TSI148_LCSR_INTS_IRQ5S | TSI148_LCSR_INTS_IRQ4S | - TSI148_LCSR_INTS_IRQ3S | TSI148_LCSR_INTS_IRQ2S | - TSI148_LCSR_INTS_IRQ1S)) - serviced |= tsi148_VIRQ_irqhandler(tsi148_bridge, stat); - - /* Clear serviced interrupts */ - iowrite32be(serviced, bridge->base + TSI148_LCSR_INTC); - - return IRQ_HANDLED; -} - -static int tsi148_irq_init(struct vme_bridge *tsi148_bridge) -{ - int result; - unsigned int tmp; - struct pci_dev *pdev; - struct tsi148_driver *bridge; - - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); - - bridge = tsi148_bridge->driver_priv; - - /* Initialise list for VME bus errors */ - INIT_LIST_HEAD(&tsi148_bridge->vme_errors); - - mutex_init(&tsi148_bridge->irq_mtx); - - result = request_irq(pdev->irq, - tsi148_irqhandler, - IRQF_SHARED, - driver_name, tsi148_bridge); - if (result) { - dev_err(tsi148_bridge->parent, "Can't get assigned pci irq " - "vector %02X\n", pdev->irq); - return result; - } - - /* Enable and unmask interrupts */ - tmp = TSI148_LCSR_INTEO_DMA1EO | TSI148_LCSR_INTEO_DMA0EO | - TSI148_LCSR_INTEO_MB3EO | TSI148_LCSR_INTEO_MB2EO | - TSI148_LCSR_INTEO_MB1EO | TSI148_LCSR_INTEO_MB0EO | - TSI148_LCSR_INTEO_PERREO | TSI148_LCSR_INTEO_VERREO | - TSI148_LCSR_INTEO_IACKEO; - - /* This leaves the following interrupts masked. - * TSI148_LCSR_INTEO_VIEEO - * TSI148_LCSR_INTEO_SYSFLEO - * TSI148_LCSR_INTEO_ACFLEO - */ - - /* Don't enable Location Monitor interrupts here - they will be - * enabled when the location monitors are properly configured and - * a callback has been attached. - * TSI148_LCSR_INTEO_LM0EO - * TSI148_LCSR_INTEO_LM1EO - * TSI148_LCSR_INTEO_LM2EO - * TSI148_LCSR_INTEO_LM3EO - */ - - /* Don't enable VME interrupts until we add a handler, else the board - * will respond to it and we don't want that unless it knows how to - * properly deal with it. - * TSI148_LCSR_INTEO_IRQ7EO - * TSI148_LCSR_INTEO_IRQ6EO - * TSI148_LCSR_INTEO_IRQ5EO - * TSI148_LCSR_INTEO_IRQ4EO - * TSI148_LCSR_INTEO_IRQ3EO - * TSI148_LCSR_INTEO_IRQ2EO - * TSI148_LCSR_INTEO_IRQ1EO - */ - - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); - - return 0; -} - -static void tsi148_irq_exit(struct vme_bridge *tsi148_bridge, - struct pci_dev *pdev) -{ - struct tsi148_driver *bridge = tsi148_bridge->driver_priv; - - /* Turn off interrupts */ - iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEO); - iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEN); - - /* Clear all interrupts */ - iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_INTC); - - /* Detach interrupt handler */ - free_irq(pdev->irq, tsi148_bridge); -} - -/* - * Check to see if an IACk has been received, return true (1) or false (0). - */ -static int tsi148_iack_received(struct tsi148_driver *bridge) -{ - u32 tmp; - - tmp = ioread32be(bridge->base + TSI148_LCSR_VICR); - - if (tmp & TSI148_LCSR_VICR_IRQS) - return 0; - else - return 1; -} - -/* - * Configure VME interrupt - */ -static void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level, - int state, int sync) -{ - struct pci_dev *pdev; - u32 tmp; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - /* We need to do the ordering differently for enabling and disabling */ - if (state == 0) { - tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); - tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1]; - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); - - tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); - tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1]; - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - - if (sync != 0) { - pdev = container_of(tsi148_bridge->parent, - struct pci_dev, dev); - - synchronize_irq(pdev->irq); - } - } else { - tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); - tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1]; - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - - tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); - tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1]; - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); - } -} - -/* - * Generate a VME bus interrupt at the requested level & vector. Wait for - * interrupt to be acked. - */ -static int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level, - int statid) -{ - u32 tmp; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - mutex_lock(&bridge->vme_int); - - /* Read VICR register */ - tmp = ioread32be(bridge->base + TSI148_LCSR_VICR); - - /* Set Status/ID */ - tmp = (tmp & ~TSI148_LCSR_VICR_STID_M) | - (statid & TSI148_LCSR_VICR_STID_M); - iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR); - - /* Assert VMEbus IRQ */ - tmp = tmp | TSI148_LCSR_VICR_IRQL[level]; - iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR); - - /* XXX Consider implementing a timeout? */ - wait_event_interruptible(bridge->iack_queue, - tsi148_iack_received(bridge)); - - mutex_unlock(&bridge->vme_int); - - return 0; -} - -/* - * Find the first error in this address range - */ -static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge, - u32 aspace, unsigned long long address, size_t count) -{ - struct list_head *err_pos; - struct vme_bus_error *vme_err, *valid = NULL; - unsigned long long bound; - - bound = address + count; - - /* - * XXX We are currently not looking at the address space when parsing - * for errors. This is because parsing the Address Modifier Codes - * is going to be quite resource intensive to do properly. We - * should be OK just looking at the addresses and this is certainly - * much better than what we had before. - */ - err_pos = NULL; - /* Iterate through errors */ - list_for_each(err_pos, &tsi148_bridge->vme_errors) { - vme_err = list_entry(err_pos, struct vme_bus_error, list); - if ((vme_err->address >= address) && - (vme_err->address < bound)) { - - valid = vme_err; - break; - } - } - - return valid; -} - -/* - * Clear errors in the provided address range. - */ -static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge, - u32 aspace, unsigned long long address, size_t count) -{ - struct list_head *err_pos, *temp; - struct vme_bus_error *vme_err; - unsigned long long bound; - - bound = address + count; - - /* - * XXX We are currently not looking at the address space when parsing - * for errors. This is because parsing the Address Modifier Codes - * is going to be quite resource intensive to do properly. We - * should be OK just looking at the addresses and this is certainly - * much better than what we had before. - */ - err_pos = NULL; - /* Iterate through errors */ - list_for_each_safe(err_pos, temp, &tsi148_bridge->vme_errors) { - vme_err = list_entry(err_pos, struct vme_bus_error, list); - - if ((vme_err->address >= address) && - (vme_err->address < bound)) { - - list_del(err_pos); - kfree(vme_err); - } - } -} - -/* - * Initialize a slave window with the requested attributes. - */ -static int tsi148_slave_set(struct vme_slave_resource *image, int enabled, - unsigned long long vme_base, unsigned long long size, - dma_addr_t pci_base, u32 aspace, u32 cycle) -{ - unsigned int i, addr = 0, granularity = 0; - unsigned int temp_ctl = 0; - unsigned int vme_base_low, vme_base_high; - unsigned int vme_bound_low, vme_bound_high; - unsigned int pci_offset_low, pci_offset_high; - unsigned long long vme_bound, pci_offset; - struct vme_bridge *tsi148_bridge; - struct tsi148_driver *bridge; - - tsi148_bridge = image->parent; - bridge = tsi148_bridge->driver_priv; - - i = image->number; - - switch (aspace) { - case VME_A16: - granularity = 0x10; - addr |= TSI148_LCSR_ITAT_AS_A16; - break; - case VME_A24: - granularity = 0x1000; - addr |= TSI148_LCSR_ITAT_AS_A24; - break; - case VME_A32: - granularity = 0x10000; - addr |= TSI148_LCSR_ITAT_AS_A32; - break; - case VME_A64: - granularity = 0x10000; - addr |= TSI148_LCSR_ITAT_AS_A64; - break; - case VME_CRCSR: - case VME_USER1: - case VME_USER2: - case VME_USER3: - case VME_USER4: - default: - dev_err(tsi148_bridge->parent, "Invalid address space\n"); - return -EINVAL; - break; - } - - /* Convert 64-bit variables to 2x 32-bit variables */ - reg_split(vme_base, &vme_base_high, &vme_base_low); - - /* - * Bound address is a valid address for the window, adjust - * accordingly - */ - vme_bound = vme_base + size - granularity; - reg_split(vme_bound, &vme_bound_high, &vme_bound_low); - pci_offset = (unsigned long long)pci_base - vme_base; - reg_split(pci_offset, &pci_offset_high, &pci_offset_low); - - if (vme_base_low & (granularity - 1)) { - dev_err(tsi148_bridge->parent, "Invalid VME base alignment\n"); - return -EINVAL; - } - if (vme_bound_low & (granularity - 1)) { - dev_err(tsi148_bridge->parent, "Invalid VME bound alignment\n"); - return -EINVAL; - } - if (pci_offset_low & (granularity - 1)) { - dev_err(tsi148_bridge->parent, "Invalid PCI Offset " - "alignment\n"); - return -EINVAL; - } - - /* Disable while we are mucking around */ - temp_ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITAT); - temp_ctl &= ~TSI148_LCSR_ITAT_EN; - iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITAT); - - /* Setup mapping */ - iowrite32be(vme_base_high, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITSAU); - iowrite32be(vme_base_low, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITSAL); - iowrite32be(vme_bound_high, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITEAU); - iowrite32be(vme_bound_low, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITEAL); - iowrite32be(pci_offset_high, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITOFU); - iowrite32be(pci_offset_low, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITOFL); - - /* Setup 2eSST speeds */ - temp_ctl &= ~TSI148_LCSR_ITAT_2eSSTM_M; - switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { - case VME_2eSST160: - temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_160; - break; - case VME_2eSST267: - temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_267; - break; - case VME_2eSST320: - temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_320; - break; - } - - /* Setup cycle types */ - temp_ctl &= ~(0x1F << 7); - if (cycle & VME_BLT) - temp_ctl |= TSI148_LCSR_ITAT_BLT; - if (cycle & VME_MBLT) - temp_ctl |= TSI148_LCSR_ITAT_MBLT; - if (cycle & VME_2eVME) - temp_ctl |= TSI148_LCSR_ITAT_2eVME; - if (cycle & VME_2eSST) - temp_ctl |= TSI148_LCSR_ITAT_2eSST; - if (cycle & VME_2eSSTB) - temp_ctl |= TSI148_LCSR_ITAT_2eSSTB; - - /* Setup address space */ - temp_ctl &= ~TSI148_LCSR_ITAT_AS_M; - temp_ctl |= addr; - - temp_ctl &= ~0xF; - if (cycle & VME_SUPER) - temp_ctl |= TSI148_LCSR_ITAT_SUPR ; - if (cycle & VME_USER) - temp_ctl |= TSI148_LCSR_ITAT_NPRIV; - if (cycle & VME_PROG) - temp_ctl |= TSI148_LCSR_ITAT_PGM; - if (cycle & VME_DATA) - temp_ctl |= TSI148_LCSR_ITAT_DATA; - - /* Write ctl reg without enable */ - iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITAT); - - if (enabled) - temp_ctl |= TSI148_LCSR_ITAT_EN; - - iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITAT); - - return 0; -} - -/* - * Get slave window configuration. - */ -static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled, - unsigned long long *vme_base, unsigned long long *size, - dma_addr_t *pci_base, u32 *aspace, u32 *cycle) -{ - unsigned int i, granularity = 0, ctl = 0; - unsigned int vme_base_low, vme_base_high; - unsigned int vme_bound_low, vme_bound_high; - unsigned int pci_offset_low, pci_offset_high; - unsigned long long vme_bound, pci_offset; - struct tsi148_driver *bridge; - - bridge = image->parent->driver_priv; - - i = image->number; - - /* Read registers */ - ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITAT); - - vme_base_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITSAU); - vme_base_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITSAL); - vme_bound_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITEAU); - vme_bound_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITEAL); - pci_offset_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITOFU); - pci_offset_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITOFL); - - /* Convert 64-bit variables to 2x 32-bit variables */ - reg_join(vme_base_high, vme_base_low, vme_base); - reg_join(vme_bound_high, vme_bound_low, &vme_bound); - reg_join(pci_offset_high, pci_offset_low, &pci_offset); - - *pci_base = (dma_addr_t)vme_base + pci_offset; - - *enabled = 0; - *aspace = 0; - *cycle = 0; - - if (ctl & TSI148_LCSR_ITAT_EN) - *enabled = 1; - - if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A16) { - granularity = 0x10; - *aspace |= VME_A16; - } - if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A24) { - granularity = 0x1000; - *aspace |= VME_A24; - } - if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A32) { - granularity = 0x10000; - *aspace |= VME_A32; - } - if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A64) { - granularity = 0x10000; - *aspace |= VME_A64; - } - - /* Need granularity before we set the size */ - *size = (unsigned long long)((vme_bound - *vme_base) + granularity); - - - if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_160) - *cycle |= VME_2eSST160; - if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_267) - *cycle |= VME_2eSST267; - if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_320) - *cycle |= VME_2eSST320; - - if (ctl & TSI148_LCSR_ITAT_BLT) - *cycle |= VME_BLT; - if (ctl & TSI148_LCSR_ITAT_MBLT) - *cycle |= VME_MBLT; - if (ctl & TSI148_LCSR_ITAT_2eVME) - *cycle |= VME_2eVME; - if (ctl & TSI148_LCSR_ITAT_2eSST) - *cycle |= VME_2eSST; - if (ctl & TSI148_LCSR_ITAT_2eSSTB) - *cycle |= VME_2eSSTB; - - if (ctl & TSI148_LCSR_ITAT_SUPR) - *cycle |= VME_SUPER; - if (ctl & TSI148_LCSR_ITAT_NPRIV) - *cycle |= VME_USER; - if (ctl & TSI148_LCSR_ITAT_PGM) - *cycle |= VME_PROG; - if (ctl & TSI148_LCSR_ITAT_DATA) - *cycle |= VME_DATA; - - return 0; -} - -/* - * Allocate and map PCI Resource - */ -static int tsi148_alloc_resource(struct vme_master_resource *image, - unsigned long long size) -{ - unsigned long long existing_size; - int retval = 0; - struct pci_dev *pdev; - struct vme_bridge *tsi148_bridge; - - tsi148_bridge = image->parent; - - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); - - existing_size = (unsigned long long)(image->bus_resource.end - - image->bus_resource.start); - - /* If the existing size is OK, return */ - if ((size != 0) && (existing_size == (size - 1))) - return 0; - - if (existing_size != 0) { - iounmap(image->kern_base); - image->kern_base = NULL; - kfree(image->bus_resource.name); - release_resource(&image->bus_resource); - memset(&image->bus_resource, 0, sizeof(struct resource)); - } - - /* Exit here if size is zero */ - if (size == 0) - return 0; - - if (image->bus_resource.name == NULL) { - image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); - if (image->bus_resource.name == NULL) { - dev_err(tsi148_bridge->parent, "Unable to allocate " - "memory for resource name\n"); - retval = -ENOMEM; - goto err_name; - } - } - - sprintf((char *)image->bus_resource.name, "%s.%d", tsi148_bridge->name, - image->number); - - image->bus_resource.start = 0; - image->bus_resource.end = (unsigned long)size; - image->bus_resource.flags = IORESOURCE_MEM; - - retval = pci_bus_alloc_resource(pdev->bus, - &image->bus_resource, size, size, PCIBIOS_MIN_MEM, - 0, NULL, NULL); - if (retval) { - dev_err(tsi148_bridge->parent, "Failed to allocate mem " - "resource for window %d size 0x%lx start 0x%lx\n", - image->number, (unsigned long)size, - (unsigned long)image->bus_resource.start); - goto err_resource; - } - - image->kern_base = ioremap_nocache( - image->bus_resource.start, size); - if (image->kern_base == NULL) { - dev_err(tsi148_bridge->parent, "Failed to remap resource\n"); - retval = -ENOMEM; - goto err_remap; - } - - return 0; - -err_remap: - release_resource(&image->bus_resource); -err_resource: - kfree(image->bus_resource.name); - memset(&image->bus_resource, 0, sizeof(struct resource)); -err_name: - return retval; -} - -/* - * Free and unmap PCI Resource - */ -static void tsi148_free_resource(struct vme_master_resource *image) -{ - iounmap(image->kern_base); - image->kern_base = NULL; - release_resource(&image->bus_resource); - kfree(image->bus_resource.name); - memset(&image->bus_resource, 0, sizeof(struct resource)); -} - -/* - * Set the attributes of an outbound window. - */ -static int tsi148_master_set(struct vme_master_resource *image, int enabled, - unsigned long long vme_base, unsigned long long size, u32 aspace, - u32 cycle, u32 dwidth) -{ - int retval = 0; - unsigned int i; - unsigned int temp_ctl = 0; - unsigned int pci_base_low, pci_base_high; - unsigned int pci_bound_low, pci_bound_high; - unsigned int vme_offset_low, vme_offset_high; - unsigned long long pci_bound, vme_offset, pci_base; - struct vme_bridge *tsi148_bridge; - struct tsi148_driver *bridge; - - tsi148_bridge = image->parent; - - bridge = tsi148_bridge->driver_priv; - - /* Verify input data */ - if (vme_base & 0xFFFF) { - dev_err(tsi148_bridge->parent, "Invalid VME Window " - "alignment\n"); - retval = -EINVAL; - goto err_window; - } - - if ((size == 0) && (enabled != 0)) { - dev_err(tsi148_bridge->parent, "Size must be non-zero for " - "enabled windows\n"); - retval = -EINVAL; - goto err_window; - } - - spin_lock(&image->lock); - - /* Let's allocate the resource here rather than further up the stack as - * it avoids pushing loads of bus dependent stuff up the stack. If size - * is zero, any existing resource will be freed. - */ - retval = tsi148_alloc_resource(image, size); - if (retval) { - spin_unlock(&image->lock); - dev_err(tsi148_bridge->parent, "Unable to allocate memory for " - "resource\n"); - goto err_res; - } - - if (size == 0) { - pci_base = 0; - pci_bound = 0; - vme_offset = 0; - } else { - pci_base = (unsigned long long)image->bus_resource.start; - - /* - * Bound address is a valid address for the window, adjust - * according to window granularity. - */ - pci_bound = pci_base + (size - 0x10000); - vme_offset = vme_base - pci_base; - } - - /* Convert 64-bit variables to 2x 32-bit variables */ - reg_split(pci_base, &pci_base_high, &pci_base_low); - reg_split(pci_bound, &pci_bound_high, &pci_bound_low); - reg_split(vme_offset, &vme_offset_high, &vme_offset_low); - - if (pci_base_low & 0xFFFF) { - spin_unlock(&image->lock); - dev_err(tsi148_bridge->parent, "Invalid PCI base alignment\n"); - retval = -EINVAL; - goto err_gran; - } - if (pci_bound_low & 0xFFFF) { - spin_unlock(&image->lock); - dev_err(tsi148_bridge->parent, "Invalid PCI bound alignment\n"); - retval = -EINVAL; - goto err_gran; - } - if (vme_offset_low & 0xFFFF) { - spin_unlock(&image->lock); - dev_err(tsi148_bridge->parent, "Invalid VME Offset " - "alignment\n"); - retval = -EINVAL; - goto err_gran; - } - - i = image->number; - - /* Disable while we are mucking around */ - temp_ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTAT); - temp_ctl &= ~TSI148_LCSR_OTAT_EN; - iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTAT); - - /* Setup 2eSST speeds */ - temp_ctl &= ~TSI148_LCSR_OTAT_2eSSTM_M; - switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { - case VME_2eSST160: - temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_160; - break; - case VME_2eSST267: - temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_267; - break; - case VME_2eSST320: - temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_320; - break; - } - - /* Setup cycle types */ - if (cycle & VME_BLT) { - temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; - temp_ctl |= TSI148_LCSR_OTAT_TM_BLT; - } - if (cycle & VME_MBLT) { - temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; - temp_ctl |= TSI148_LCSR_OTAT_TM_MBLT; - } - if (cycle & VME_2eVME) { - temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; - temp_ctl |= TSI148_LCSR_OTAT_TM_2eVME; - } - if (cycle & VME_2eSST) { - temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; - temp_ctl |= TSI148_LCSR_OTAT_TM_2eSST; - } - if (cycle & VME_2eSSTB) { - dev_warn(tsi148_bridge->parent, "Currently not setting " - "Broadcast Select Registers\n"); - temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; - temp_ctl |= TSI148_LCSR_OTAT_TM_2eSSTB; - } - - /* Setup data width */ - temp_ctl &= ~TSI148_LCSR_OTAT_DBW_M; - switch (dwidth) { - case VME_D16: - temp_ctl |= TSI148_LCSR_OTAT_DBW_16; - break; - case VME_D32: - temp_ctl |= TSI148_LCSR_OTAT_DBW_32; - break; - default: - spin_unlock(&image->lock); - dev_err(tsi148_bridge->parent, "Invalid data width\n"); - retval = -EINVAL; - goto err_dwidth; - } - - /* Setup address space */ - temp_ctl &= ~TSI148_LCSR_OTAT_AMODE_M; - switch (aspace) { - case VME_A16: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_A16; - break; - case VME_A24: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_A24; - break; - case VME_A32: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_A32; - break; - case VME_A64: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_A64; - break; - case VME_CRCSR: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_CRCSR; - break; - case VME_USER1: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER1; - break; - case VME_USER2: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER2; - break; - case VME_USER3: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER3; - break; - case VME_USER4: - temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER4; - break; - default: - spin_unlock(&image->lock); - dev_err(tsi148_bridge->parent, "Invalid address space\n"); - retval = -EINVAL; - goto err_aspace; - break; - } - - temp_ctl &= ~(3<<4); - if (cycle & VME_SUPER) - temp_ctl |= TSI148_LCSR_OTAT_SUP; - if (cycle & VME_PROG) - temp_ctl |= TSI148_LCSR_OTAT_PGM; - - /* Setup mapping */ - iowrite32be(pci_base_high, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTSAU); - iowrite32be(pci_base_low, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTSAL); - iowrite32be(pci_bound_high, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTEAU); - iowrite32be(pci_bound_low, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTEAL); - iowrite32be(vme_offset_high, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTOFU); - iowrite32be(vme_offset_low, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTOFL); - - /* Write ctl reg without enable */ - iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTAT); - - if (enabled) - temp_ctl |= TSI148_LCSR_OTAT_EN; - - iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTAT); - - spin_unlock(&image->lock); - return 0; - -err_aspace: -err_dwidth: -err_gran: - tsi148_free_resource(image); -err_res: -err_window: - return retval; - -} - -/* - * Set the attributes of an outbound window. - * - * XXX Not parsing prefetch information. - */ -static int __tsi148_master_get(struct vme_master_resource *image, int *enabled, - unsigned long long *vme_base, unsigned long long *size, u32 *aspace, - u32 *cycle, u32 *dwidth) -{ - unsigned int i, ctl; - unsigned int pci_base_low, pci_base_high; - unsigned int pci_bound_low, pci_bound_high; - unsigned int vme_offset_low, vme_offset_high; - - unsigned long long pci_base, pci_bound, vme_offset; - struct tsi148_driver *bridge; - - bridge = image->parent->driver_priv; - - i = image->number; - - ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTAT); - - pci_base_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTSAU); - pci_base_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTSAL); - pci_bound_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTEAU); - pci_bound_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTEAL); - vme_offset_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTOFU); - vme_offset_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTOFL); - - /* Convert 64-bit variables to 2x 32-bit variables */ - reg_join(pci_base_high, pci_base_low, &pci_base); - reg_join(pci_bound_high, pci_bound_low, &pci_bound); - reg_join(vme_offset_high, vme_offset_low, &vme_offset); - - *vme_base = pci_base + vme_offset; - *size = (unsigned long long)(pci_bound - pci_base) + 0x10000; - - *enabled = 0; - *aspace = 0; - *cycle = 0; - *dwidth = 0; - - if (ctl & TSI148_LCSR_OTAT_EN) - *enabled = 1; - - /* Setup address space */ - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A16) - *aspace |= VME_A16; - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A24) - *aspace |= VME_A24; - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A32) - *aspace |= VME_A32; - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A64) - *aspace |= VME_A64; - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_CRCSR) - *aspace |= VME_CRCSR; - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER1) - *aspace |= VME_USER1; - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER2) - *aspace |= VME_USER2; - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER3) - *aspace |= VME_USER3; - if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER4) - *aspace |= VME_USER4; - - /* Setup 2eSST speeds */ - if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_160) - *cycle |= VME_2eSST160; - if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_267) - *cycle |= VME_2eSST267; - if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_320) - *cycle |= VME_2eSST320; - - /* Setup cycle types */ - if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_SCT) - *cycle |= VME_SCT; - if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_BLT) - *cycle |= VME_BLT; - if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_MBLT) - *cycle |= VME_MBLT; - if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eVME) - *cycle |= VME_2eVME; - if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSST) - *cycle |= VME_2eSST; - if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSSTB) - *cycle |= VME_2eSSTB; - - if (ctl & TSI148_LCSR_OTAT_SUP) - *cycle |= VME_SUPER; - else - *cycle |= VME_USER; - - if (ctl & TSI148_LCSR_OTAT_PGM) - *cycle |= VME_PROG; - else - *cycle |= VME_DATA; - - /* Setup data width */ - if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_16) - *dwidth = VME_D16; - if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_32) - *dwidth = VME_D32; - - return 0; -} - - -static int tsi148_master_get(struct vme_master_resource *image, int *enabled, - unsigned long long *vme_base, unsigned long long *size, u32 *aspace, - u32 *cycle, u32 *dwidth) -{ - int retval; - - spin_lock(&image->lock); - - retval = __tsi148_master_get(image, enabled, vme_base, size, aspace, - cycle, dwidth); - - spin_unlock(&image->lock); - - return retval; -} - -static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, - size_t count, loff_t offset) -{ - int retval, enabled; - unsigned long long vme_base, size; - u32 aspace, cycle, dwidth; - struct vme_bus_error *vme_err = NULL; - struct vme_bridge *tsi148_bridge; - - tsi148_bridge = image->parent; - - spin_lock(&image->lock); - - memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count); - retval = count; - - if (!err_chk) - goto skip_chk; - - __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, - &dwidth); - - vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, - count); - if (vme_err != NULL) { - dev_err(image->parent->parent, "First VME read error detected " - "an at address 0x%llx\n", vme_err->address); - retval = vme_err->address - (vme_base + offset); - /* Clear down save errors in this address range */ - tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, - count); - } - -skip_chk: - spin_unlock(&image->lock); - - return retval; -} - - -static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, - size_t count, loff_t offset) -{ - int retval = 0, enabled; - unsigned long long vme_base, size; - u32 aspace, cycle, dwidth; - - struct vme_bus_error *vme_err = NULL; - struct vme_bridge *tsi148_bridge; - struct tsi148_driver *bridge; - - tsi148_bridge = image->parent; - - bridge = tsi148_bridge->driver_priv; - - spin_lock(&image->lock); - - memcpy_toio(image->kern_base + offset, buf, (unsigned int)count); - retval = count; - - /* - * Writes are posted. We need to do a read on the VME bus to flush out - * all of the writes before we check for errors. We can't guarantee - * that reading the data we have just written is safe. It is believed - * that there isn't any read, write re-ordering, so we can read any - * location in VME space, so lets read the Device ID from the tsi148's - * own registers as mapped into CR/CSR space. - * - * We check for saved errors in the written address range/space. - */ - - if (!err_chk) - goto skip_chk; - - /* - * Get window info first, to maximise the time that the buffers may - * fluch on their own - */ - __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, - &dwidth); - - ioread16(bridge->flush_image->kern_base + 0x7F000); - - vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, - count); - if (vme_err != NULL) { - dev_warn(tsi148_bridge->parent, "First VME write error detected" - " an at address 0x%llx\n", vme_err->address); - retval = vme_err->address - (vme_base + offset); - /* Clear down save errors in this address range */ - tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, - count); - } - -skip_chk: - spin_unlock(&image->lock); - - return retval; -} - -/* - * Perform an RMW cycle on the VME bus. - * - * Requires a previously configured master window, returns final value. - */ -static unsigned int tsi148_master_rmw(struct vme_master_resource *image, - unsigned int mask, unsigned int compare, unsigned int swap, - loff_t offset) -{ - unsigned long long pci_addr; - unsigned int pci_addr_high, pci_addr_low; - u32 tmp, result; - int i; - struct tsi148_driver *bridge; - - bridge = image->parent->driver_priv; - - /* Find the PCI address that maps to the desired VME address */ - i = image->number; - - /* Locking as we can only do one of these at a time */ - mutex_lock(&bridge->vme_rmw); - - /* Lock image */ - spin_lock(&image->lock); - - pci_addr_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTSAU); - pci_addr_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTSAL); - - reg_join(pci_addr_high, pci_addr_low, &pci_addr); - reg_split(pci_addr + offset, &pci_addr_high, &pci_addr_low); - - /* Configure registers */ - iowrite32be(mask, bridge->base + TSI148_LCSR_RMWEN); - iowrite32be(compare, bridge->base + TSI148_LCSR_RMWC); - iowrite32be(swap, bridge->base + TSI148_LCSR_RMWS); - iowrite32be(pci_addr_high, bridge->base + TSI148_LCSR_RMWAU); - iowrite32be(pci_addr_low, bridge->base + TSI148_LCSR_RMWAL); - - /* Enable RMW */ - tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL); - tmp |= TSI148_LCSR_VMCTRL_RMWEN; - iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL); - - /* Kick process off with a read to the required address. */ - result = ioread32be(image->kern_base + offset); - - /* Disable RMW */ - tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL); - tmp &= ~TSI148_LCSR_VMCTRL_RMWEN; - iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL); - - spin_unlock(&image->lock); - - mutex_unlock(&bridge->vme_rmw); - - return result; -} - -static int tsi148_dma_set_vme_src_attributes(struct device *dev, __be32 *attr, - u32 aspace, u32 cycle, u32 dwidth) -{ - u32 val; - - val = be32_to_cpu(*attr); - - /* Setup 2eSST speeds */ - switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { - case VME_2eSST160: - val |= TSI148_LCSR_DSAT_2eSSTM_160; - break; - case VME_2eSST267: - val |= TSI148_LCSR_DSAT_2eSSTM_267; - break; - case VME_2eSST320: - val |= TSI148_LCSR_DSAT_2eSSTM_320; - break; - } - - /* Setup cycle types */ - if (cycle & VME_SCT) - val |= TSI148_LCSR_DSAT_TM_SCT; - - if (cycle & VME_BLT) - val |= TSI148_LCSR_DSAT_TM_BLT; - - if (cycle & VME_MBLT) - val |= TSI148_LCSR_DSAT_TM_MBLT; - - if (cycle & VME_2eVME) - val |= TSI148_LCSR_DSAT_TM_2eVME; - - if (cycle & VME_2eSST) - val |= TSI148_LCSR_DSAT_TM_2eSST; - - if (cycle & VME_2eSSTB) { - dev_err(dev, "Currently not setting Broadcast Select " - "Registers\n"); - val |= TSI148_LCSR_DSAT_TM_2eSSTB; - } - - /* Setup data width */ - switch (dwidth) { - case VME_D16: - val |= TSI148_LCSR_DSAT_DBW_16; - break; - case VME_D32: - val |= TSI148_LCSR_DSAT_DBW_32; - break; - default: - dev_err(dev, "Invalid data width\n"); - return -EINVAL; - } - - /* Setup address space */ - switch (aspace) { - case VME_A16: - val |= TSI148_LCSR_DSAT_AMODE_A16; - break; - case VME_A24: - val |= TSI148_LCSR_DSAT_AMODE_A24; - break; - case VME_A32: - val |= TSI148_LCSR_DSAT_AMODE_A32; - break; - case VME_A64: - val |= TSI148_LCSR_DSAT_AMODE_A64; - break; - case VME_CRCSR: - val |= TSI148_LCSR_DSAT_AMODE_CRCSR; - break; - case VME_USER1: - val |= TSI148_LCSR_DSAT_AMODE_USER1; - break; - case VME_USER2: - val |= TSI148_LCSR_DSAT_AMODE_USER2; - break; - case VME_USER3: - val |= TSI148_LCSR_DSAT_AMODE_USER3; - break; - case VME_USER4: - val |= TSI148_LCSR_DSAT_AMODE_USER4; - break; - default: - dev_err(dev, "Invalid address space\n"); - return -EINVAL; - break; - } - - if (cycle & VME_SUPER) - val |= TSI148_LCSR_DSAT_SUP; - if (cycle & VME_PROG) - val |= TSI148_LCSR_DSAT_PGM; - - *attr = cpu_to_be32(val); - - return 0; -} - -static int tsi148_dma_set_vme_dest_attributes(struct device *dev, __be32 *attr, - u32 aspace, u32 cycle, u32 dwidth) -{ - u32 val; - - val = be32_to_cpu(*attr); - - /* Setup 2eSST speeds */ - switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { - case VME_2eSST160: - val |= TSI148_LCSR_DDAT_2eSSTM_160; - break; - case VME_2eSST267: - val |= TSI148_LCSR_DDAT_2eSSTM_267; - break; - case VME_2eSST320: - val |= TSI148_LCSR_DDAT_2eSSTM_320; - break; - } - - /* Setup cycle types */ - if (cycle & VME_SCT) - val |= TSI148_LCSR_DDAT_TM_SCT; - - if (cycle & VME_BLT) - val |= TSI148_LCSR_DDAT_TM_BLT; - - if (cycle & VME_MBLT) - val |= TSI148_LCSR_DDAT_TM_MBLT; - - if (cycle & VME_2eVME) - val |= TSI148_LCSR_DDAT_TM_2eVME; - - if (cycle & VME_2eSST) - val |= TSI148_LCSR_DDAT_TM_2eSST; - - if (cycle & VME_2eSSTB) { - dev_err(dev, "Currently not setting Broadcast Select " - "Registers\n"); - val |= TSI148_LCSR_DDAT_TM_2eSSTB; - } - - /* Setup data width */ - switch (dwidth) { - case VME_D16: - val |= TSI148_LCSR_DDAT_DBW_16; - break; - case VME_D32: - val |= TSI148_LCSR_DDAT_DBW_32; - break; - default: - dev_err(dev, "Invalid data width\n"); - return -EINVAL; - } - - /* Setup address space */ - switch (aspace) { - case VME_A16: - val |= TSI148_LCSR_DDAT_AMODE_A16; - break; - case VME_A24: - val |= TSI148_LCSR_DDAT_AMODE_A24; - break; - case VME_A32: - val |= TSI148_LCSR_DDAT_AMODE_A32; - break; - case VME_A64: - val |= TSI148_LCSR_DDAT_AMODE_A64; - break; - case VME_CRCSR: - val |= TSI148_LCSR_DDAT_AMODE_CRCSR; - break; - case VME_USER1: - val |= TSI148_LCSR_DDAT_AMODE_USER1; - break; - case VME_USER2: - val |= TSI148_LCSR_DDAT_AMODE_USER2; - break; - case VME_USER3: - val |= TSI148_LCSR_DDAT_AMODE_USER3; - break; - case VME_USER4: - val |= TSI148_LCSR_DDAT_AMODE_USER4; - break; - default: - dev_err(dev, "Invalid address space\n"); - return -EINVAL; - break; - } - - if (cycle & VME_SUPER) - val |= TSI148_LCSR_DDAT_SUP; - if (cycle & VME_PROG) - val |= TSI148_LCSR_DDAT_PGM; - - *attr = cpu_to_be32(val); - - return 0; -} - -/* - * Add a link list descriptor to the list - * - * Note: DMA engine expects the DMA descriptor to be big endian. - */ -static int tsi148_dma_list_add(struct vme_dma_list *list, - struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count) -{ - struct tsi148_dma_entry *entry, *prev; - u32 address_high, address_low, val; - struct vme_dma_pattern *pattern_attr; - struct vme_dma_pci *pci_attr; - struct vme_dma_vme *vme_attr; - int retval = 0; - struct vme_bridge *tsi148_bridge; - - tsi148_bridge = list->parent->parent; - - /* Descriptor must be aligned on 64-bit boundaries */ - entry = kmalloc(sizeof(struct tsi148_dma_entry), GFP_KERNEL); - if (entry == NULL) { - dev_err(tsi148_bridge->parent, "Failed to allocate memory for " - "dma resource structure\n"); - retval = -ENOMEM; - goto err_mem; - } - - /* Test descriptor alignment */ - if ((unsigned long)&entry->descriptor & 0x7) { - dev_err(tsi148_bridge->parent, "Descriptor not aligned to 8 " - "byte boundary as required: %p\n", - &entry->descriptor); - retval = -EINVAL; - goto err_align; - } - - /* Given we are going to fill out the structure, we probably don't - * need to zero it, but better safe than sorry for now. - */ - memset(&entry->descriptor, 0, sizeof(struct tsi148_dma_descriptor)); - - /* Fill out source part */ - switch (src->type) { - case VME_DMA_PATTERN: - pattern_attr = src->private; - - entry->descriptor.dsal = cpu_to_be32(pattern_attr->pattern); - - val = TSI148_LCSR_DSAT_TYP_PAT; - - /* Default behaviour is 32 bit pattern */ - if (pattern_attr->type & VME_DMA_PATTERN_BYTE) - val |= TSI148_LCSR_DSAT_PSZ; - - /* It seems that the default behaviour is to increment */ - if ((pattern_attr->type & VME_DMA_PATTERN_INCREMENT) == 0) - val |= TSI148_LCSR_DSAT_NIN; - entry->descriptor.dsat = cpu_to_be32(val); - break; - case VME_DMA_PCI: - pci_attr = src->private; - - reg_split((unsigned long long)pci_attr->address, &address_high, - &address_low); - entry->descriptor.dsau = cpu_to_be32(address_high); - entry->descriptor.dsal = cpu_to_be32(address_low); - entry->descriptor.dsat = cpu_to_be32(TSI148_LCSR_DSAT_TYP_PCI); - break; - case VME_DMA_VME: - vme_attr = src->private; - - reg_split((unsigned long long)vme_attr->address, &address_high, - &address_low); - entry->descriptor.dsau = cpu_to_be32(address_high); - entry->descriptor.dsal = cpu_to_be32(address_low); - entry->descriptor.dsat = cpu_to_be32(TSI148_LCSR_DSAT_TYP_VME); - - retval = tsi148_dma_set_vme_src_attributes( - tsi148_bridge->parent, &entry->descriptor.dsat, - vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth); - if (retval < 0) - goto err_source; - break; - default: - dev_err(tsi148_bridge->parent, "Invalid source type\n"); - retval = -EINVAL; - goto err_source; - break; - } - - /* Assume last link - this will be over-written by adding another */ - entry->descriptor.dnlau = cpu_to_be32(0); - entry->descriptor.dnlal = cpu_to_be32(TSI148_LCSR_DNLAL_LLA); - - /* Fill out destination part */ - switch (dest->type) { - case VME_DMA_PCI: - pci_attr = dest->private; - - reg_split((unsigned long long)pci_attr->address, &address_high, - &address_low); - entry->descriptor.ddau = cpu_to_be32(address_high); - entry->descriptor.ddal = cpu_to_be32(address_low); - entry->descriptor.ddat = cpu_to_be32(TSI148_LCSR_DDAT_TYP_PCI); - break; - case VME_DMA_VME: - vme_attr = dest->private; - - reg_split((unsigned long long)vme_attr->address, &address_high, - &address_low); - entry->descriptor.ddau = cpu_to_be32(address_high); - entry->descriptor.ddal = cpu_to_be32(address_low); - entry->descriptor.ddat = cpu_to_be32(TSI148_LCSR_DDAT_TYP_VME); - - retval = tsi148_dma_set_vme_dest_attributes( - tsi148_bridge->parent, &entry->descriptor.ddat, - vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth); - if (retval < 0) - goto err_dest; - break; - default: - dev_err(tsi148_bridge->parent, "Invalid destination type\n"); - retval = -EINVAL; - goto err_dest; - break; - } - - /* Fill out count */ - entry->descriptor.dcnt = cpu_to_be32((u32)count); - - /* Add to list */ - list_add_tail(&entry->list, &list->entries); - - /* Fill out previous descriptors "Next Address" */ - if (entry->list.prev != &list->entries) { - prev = list_entry(entry->list.prev, struct tsi148_dma_entry, - list); - /* We need the bus address for the pointer */ - entry->dma_handle = dma_map_single(tsi148_bridge->parent, - &entry->descriptor, - sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE); - - reg_split((unsigned long long)entry->dma_handle, &address_high, - &address_low); - entry->descriptor.dnlau = cpu_to_be32(address_high); - entry->descriptor.dnlal = cpu_to_be32(address_low); - - } - - return 0; - -err_dest: -err_source: -err_align: - kfree(entry); -err_mem: - return retval; -} - -/* - * Check to see if the provided DMA channel is busy. - */ -static int tsi148_dma_busy(struct vme_bridge *tsi148_bridge, int channel) -{ - u32 tmp; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - tmp = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + - TSI148_LCSR_OFFSET_DSTA); - - if (tmp & TSI148_LCSR_DSTA_BSY) - return 0; - else - return 1; - -} - -/* - * Execute a previously generated link list - * - * XXX Need to provide control register configuration. - */ -static int tsi148_dma_list_exec(struct vme_dma_list *list) -{ - struct vme_dma_resource *ctrlr; - int channel, retval = 0; - struct tsi148_dma_entry *entry; - u32 bus_addr_high, bus_addr_low; - u32 val, dctlreg = 0; - struct vme_bridge *tsi148_bridge; - struct tsi148_driver *bridge; - - ctrlr = list->parent; - - tsi148_bridge = ctrlr->parent; - - bridge = tsi148_bridge->driver_priv; - - mutex_lock(&ctrlr->mtx); - - channel = ctrlr->number; - - if (!list_empty(&ctrlr->running)) { - /* - * XXX We have an active DMA transfer and currently haven't - * sorted out the mechanism for "pending" DMA transfers. - * Return busy. - */ - /* Need to add to pending here */ - mutex_unlock(&ctrlr->mtx); - return -EBUSY; - } else { - list_add(&list->list, &ctrlr->running); - } - - /* Get first bus address and write into registers */ - entry = list_first_entry(&list->entries, struct tsi148_dma_entry, - list); - - entry->dma_handle = dma_map_single(tsi148_bridge->parent, - &entry->descriptor, - sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE); - - mutex_unlock(&ctrlr->mtx); - - reg_split(entry->dma_handle, &bus_addr_high, &bus_addr_low); - - iowrite32be(bus_addr_high, bridge->base + - TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU); - iowrite32be(bus_addr_low, bridge->base + - TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL); - - dctlreg = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + - TSI148_LCSR_OFFSET_DCTL); - - /* Start the operation */ - iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base + - TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL); - - wait_event_interruptible(bridge->dma_queue[channel], - tsi148_dma_busy(ctrlr->parent, channel)); - - /* - * Read status register, this register is valid until we kick off a - * new transfer. - */ - val = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + - TSI148_LCSR_OFFSET_DSTA); - - if (val & TSI148_LCSR_DSTA_VBE) { - dev_err(tsi148_bridge->parent, "DMA Error. DSTA=%08X\n", val); - retval = -EIO; - } - - /* Remove list from running list */ - mutex_lock(&ctrlr->mtx); - list_del(&list->list); - mutex_unlock(&ctrlr->mtx); - - return retval; -} - -/* - * Clean up a previously generated link list - * - * We have a separate function, don't assume that the chain can't be reused. - */ -static int tsi148_dma_list_empty(struct vme_dma_list *list) -{ - struct list_head *pos, *temp; - struct tsi148_dma_entry *entry; - - struct vme_bridge *tsi148_bridge = list->parent->parent; - - /* detach and free each entry */ - list_for_each_safe(pos, temp, &list->entries) { - list_del(pos); - entry = list_entry(pos, struct tsi148_dma_entry, list); - - dma_unmap_single(tsi148_bridge->parent, entry->dma_handle, - sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE); - kfree(entry); - } - - return 0; -} - -/* - * All 4 location monitors reside at the same base - this is therefore a - * system wide configuration. - * - * This does not enable the LM monitor - that should be done when the first - * callback is attached and disabled when the last callback is removed. - */ -static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, - u32 aspace, u32 cycle) -{ - u32 lm_base_high, lm_base_low, lm_ctl = 0; - int i; - struct vme_bridge *tsi148_bridge; - struct tsi148_driver *bridge; - - tsi148_bridge = lm->parent; - - bridge = tsi148_bridge->driver_priv; - - mutex_lock(&lm->mtx); - - /* If we already have a callback attached, we can't move it! */ - for (i = 0; i < lm->monitors; i++) { - if (bridge->lm_callback[i] != NULL) { - mutex_unlock(&lm->mtx); - dev_err(tsi148_bridge->parent, "Location monitor " - "callback attached, can't reset\n"); - return -EBUSY; - } - } - - switch (aspace) { - case VME_A16: - lm_ctl |= TSI148_LCSR_LMAT_AS_A16; - break; - case VME_A24: - lm_ctl |= TSI148_LCSR_LMAT_AS_A24; - break; - case VME_A32: - lm_ctl |= TSI148_LCSR_LMAT_AS_A32; - break; - case VME_A64: - lm_ctl |= TSI148_LCSR_LMAT_AS_A64; - break; - default: - mutex_unlock(&lm->mtx); - dev_err(tsi148_bridge->parent, "Invalid address space\n"); - return -EINVAL; - break; - } - - if (cycle & VME_SUPER) - lm_ctl |= TSI148_LCSR_LMAT_SUPR ; - if (cycle & VME_USER) - lm_ctl |= TSI148_LCSR_LMAT_NPRIV; - if (cycle & VME_PROG) - lm_ctl |= TSI148_LCSR_LMAT_PGM; - if (cycle & VME_DATA) - lm_ctl |= TSI148_LCSR_LMAT_DATA; - - reg_split(lm_base, &lm_base_high, &lm_base_low); - - iowrite32be(lm_base_high, bridge->base + TSI148_LCSR_LMBAU); - iowrite32be(lm_base_low, bridge->base + TSI148_LCSR_LMBAL); - iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT); - - mutex_unlock(&lm->mtx); - - return 0; -} - -/* Get configuration of the callback monitor and return whether it is enabled - * or disabled. - */ -static int tsi148_lm_get(struct vme_lm_resource *lm, - unsigned long long *lm_base, u32 *aspace, u32 *cycle) -{ - u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0; - struct tsi148_driver *bridge; - - bridge = lm->parent->driver_priv; - - mutex_lock(&lm->mtx); - - lm_base_high = ioread32be(bridge->base + TSI148_LCSR_LMBAU); - lm_base_low = ioread32be(bridge->base + TSI148_LCSR_LMBAL); - lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT); - - reg_join(lm_base_high, lm_base_low, lm_base); - - if (lm_ctl & TSI148_LCSR_LMAT_EN) - enabled = 1; - - if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A16) - *aspace |= VME_A16; - - if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A24) - *aspace |= VME_A24; - - if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A32) - *aspace |= VME_A32; - - if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A64) - *aspace |= VME_A64; - - - if (lm_ctl & TSI148_LCSR_LMAT_SUPR) - *cycle |= VME_SUPER; - if (lm_ctl & TSI148_LCSR_LMAT_NPRIV) - *cycle |= VME_USER; - if (lm_ctl & TSI148_LCSR_LMAT_PGM) - *cycle |= VME_PROG; - if (lm_ctl & TSI148_LCSR_LMAT_DATA) - *cycle |= VME_DATA; - - mutex_unlock(&lm->mtx); - - return enabled; -} - -/* - * Attach a callback to a specific location monitor. - * - * Callback will be passed the monitor triggered. - */ -static int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor, - void (*callback)(int)) -{ - u32 lm_ctl, tmp; - struct vme_bridge *tsi148_bridge; - struct tsi148_driver *bridge; - - tsi148_bridge = lm->parent; - - bridge = tsi148_bridge->driver_priv; - - mutex_lock(&lm->mtx); - - /* Ensure that the location monitor is configured - need PGM or DATA */ - lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT); - if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) { - mutex_unlock(&lm->mtx); - dev_err(tsi148_bridge->parent, "Location monitor not properly " - "configured\n"); - return -EINVAL; - } - - /* Check that a callback isn't already attached */ - if (bridge->lm_callback[monitor] != NULL) { - mutex_unlock(&lm->mtx); - dev_err(tsi148_bridge->parent, "Existing callback attached\n"); - return -EBUSY; - } - - /* Attach callback */ - bridge->lm_callback[monitor] = callback; - - /* Enable Location Monitor interrupt */ - tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); - tmp |= TSI148_LCSR_INTEN_LMEN[monitor]; - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); - - tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); - tmp |= TSI148_LCSR_INTEO_LMEO[monitor]; - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - - /* Ensure that global Location Monitor Enable set */ - if ((lm_ctl & TSI148_LCSR_LMAT_EN) == 0) { - lm_ctl |= TSI148_LCSR_LMAT_EN; - iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT); - } - - mutex_unlock(&lm->mtx); - - return 0; -} - -/* - * Detach a callback function forn a specific location monitor. - */ -static int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor) -{ - u32 lm_en, tmp; - struct tsi148_driver *bridge; - - bridge = lm->parent->driver_priv; - - mutex_lock(&lm->mtx); - - /* Disable Location Monitor and ensure previous interrupts are clear */ - lm_en = ioread32be(bridge->base + TSI148_LCSR_INTEN); - lm_en &= ~TSI148_LCSR_INTEN_LMEN[monitor]; - iowrite32be(lm_en, bridge->base + TSI148_LCSR_INTEN); - - tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); - tmp &= ~TSI148_LCSR_INTEO_LMEO[monitor]; - iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); - - iowrite32be(TSI148_LCSR_INTC_LMC[monitor], - bridge->base + TSI148_LCSR_INTC); - - /* Detach callback */ - bridge->lm_callback[monitor] = NULL; - - /* If all location monitors disabled, disable global Location Monitor */ - if ((lm_en & (TSI148_LCSR_INTS_LM0S | TSI148_LCSR_INTS_LM1S | - TSI148_LCSR_INTS_LM2S | TSI148_LCSR_INTS_LM3S)) == 0) { - tmp = ioread32be(bridge->base + TSI148_LCSR_LMAT); - tmp &= ~TSI148_LCSR_LMAT_EN; - iowrite32be(tmp, bridge->base + TSI148_LCSR_LMAT); - } - - mutex_unlock(&lm->mtx); - - return 0; -} - -/* - * Determine Geographical Addressing - */ -static int tsi148_slot_get(struct vme_bridge *tsi148_bridge) -{ - u32 slot = 0; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - if (!geoid) { - slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT); - slot = slot & TSI148_LCSR_VSTAT_GA_M; - } else - slot = geoid; - - return (int)slot; -} - -void *tsi148_alloc_consistent(struct device *parent, size_t size, - dma_addr_t *dma) -{ - struct pci_dev *pdev; - - /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); - - return pci_alloc_consistent(pdev, size, dma); -} - -void tsi148_free_consistent(struct device *parent, size_t size, void *vaddr, - dma_addr_t dma) -{ - struct pci_dev *pdev; - - /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); - - pci_free_consistent(pdev, size, vaddr, dma); -} - -static int __init tsi148_init(void) -{ - return pci_register_driver(&tsi148_driver); -} - -/* - * Configure CR/CSR space - * - * Access to the CR/CSR can be configured at power-up. The location of the - * CR/CSR registers in the CR/CSR address space is determined by the boards - * Auto-ID or Geographic address. This function ensures that the window is - * enabled at an offset consistent with the boards geopgraphic address. - * - * Each board has a 512kB window, with the highest 4kB being used for the - * boards registers, this means there is a fix length 508kB window which must - * be mapped onto PCI memory. - */ -static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge, - struct pci_dev *pdev) -{ - u32 cbar, crat, vstat; - u32 crcsr_bus_high, crcsr_bus_low; - int retval; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - /* Allocate mem for CR/CSR image */ - bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, - &bridge->crcsr_bus); - if (bridge->crcsr_kernel == NULL) { - dev_err(tsi148_bridge->parent, "Failed to allocate memory for " - "CR/CSR image\n"); - return -ENOMEM; - } - - memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); - - reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low); - - iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU); - iowrite32be(crcsr_bus_low, bridge->base + TSI148_LCSR_CROL); - - /* Ensure that the CR/CSR is configured at the correct offset */ - cbar = ioread32be(bridge->base + TSI148_CBAR); - cbar = (cbar & TSI148_CRCSR_CBAR_M)>>3; - - vstat = tsi148_slot_get(tsi148_bridge); - - if (cbar != vstat) { - cbar = vstat; - dev_info(tsi148_bridge->parent, "Setting CR/CSR offset\n"); - iowrite32be(cbar<<3, bridge->base + TSI148_CBAR); - } - dev_info(tsi148_bridge->parent, "CR/CSR Offset: %d\n", cbar); - - crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); - if (crat & TSI148_LCSR_CRAT_EN) { - dev_info(tsi148_bridge->parent, "Enabling CR/CSR space\n"); - iowrite32be(crat | TSI148_LCSR_CRAT_EN, - bridge->base + TSI148_LCSR_CRAT); - } else - dev_info(tsi148_bridge->parent, "CR/CSR already enabled\n"); - - /* If we want flushed, error-checked writes, set up a window - * over the CR/CSR registers. We read from here to safely flush - * through VME writes. - */ - if (err_chk) { - retval = tsi148_master_set(bridge->flush_image, 1, - (vstat * 0x80000), 0x80000, VME_CRCSR, VME_SCT, - VME_D16); - if (retval) - dev_err(tsi148_bridge->parent, "Configuring flush image" - " failed\n"); - } - - return 0; - -} - -static void tsi148_crcsr_exit(struct vme_bridge *tsi148_bridge, - struct pci_dev *pdev) -{ - u32 crat; - struct tsi148_driver *bridge; - - bridge = tsi148_bridge->driver_priv; - - /* Turn off CR/CSR space */ - crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); - iowrite32be(crat & ~TSI148_LCSR_CRAT_EN, - bridge->base + TSI148_LCSR_CRAT); - - /* Free image */ - iowrite32be(0, bridge->base + TSI148_LCSR_CROU); - iowrite32be(0, bridge->base + TSI148_LCSR_CROL); - - pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, - bridge->crcsr_bus); -} - -static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int retval, i, master_num; - u32 data; - struct list_head *pos = NULL; - struct vme_bridge *tsi148_bridge; - struct tsi148_driver *tsi148_device; - struct vme_master_resource *master_image; - struct vme_slave_resource *slave_image; - struct vme_dma_resource *dma_ctrlr; - struct vme_lm_resource *lm; - - /* If we want to support more than one of each bridge, we need to - * dynamically generate this so we get one per device - */ - tsi148_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); - if (tsi148_bridge == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for device " - "structure\n"); - retval = -ENOMEM; - goto err_struct; - } - - tsi148_device = kzalloc(sizeof(struct tsi148_driver), GFP_KERNEL); - if (tsi148_device == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for device " - "structure\n"); - retval = -ENOMEM; - goto err_driver; - } - - tsi148_bridge->driver_priv = tsi148_device; - - /* Enable the device */ - retval = pci_enable_device(pdev); - if (retval) { - dev_err(&pdev->dev, "Unable to enable device\n"); - goto err_enable; - } - - /* Map Registers */ - retval = pci_request_regions(pdev, driver_name); - if (retval) { - dev_err(&pdev->dev, "Unable to reserve resources\n"); - goto err_resource; - } - - /* map registers in BAR 0 */ - tsi148_device->base = ioremap_nocache(pci_resource_start(pdev, 0), - 4096); - if (!tsi148_device->base) { - dev_err(&pdev->dev, "Unable to remap CRG region\n"); - retval = -EIO; - goto err_remap; - } - - /* Check to see if the mapping worked out */ - data = ioread32(tsi148_device->base + TSI148_PCFS_ID) & 0x0000FFFF; - if (data != PCI_VENDOR_ID_TUNDRA) { - dev_err(&pdev->dev, "CRG region check failed\n"); - retval = -EIO; - goto err_test; - } - - /* Initialize wait queues & mutual exclusion flags */ - init_waitqueue_head(&tsi148_device->dma_queue[0]); - init_waitqueue_head(&tsi148_device->dma_queue[1]); - init_waitqueue_head(&tsi148_device->iack_queue); - mutex_init(&tsi148_device->vme_int); - mutex_init(&tsi148_device->vme_rmw); - - tsi148_bridge->parent = &pdev->dev; - strcpy(tsi148_bridge->name, driver_name); - - /* Setup IRQ */ - retval = tsi148_irq_init(tsi148_bridge); - if (retval != 0) { - dev_err(&pdev->dev, "Chip Initialization failed.\n"); - goto err_irq; - } - - /* If we are going to flush writes, we need to read from the VME bus. - * We need to do this safely, thus we read the devices own CR/CSR - * register. To do this we must set up a window in CR/CSR space and - * hence have one less master window resource available. - */ - master_num = TSI148_MAX_MASTER; - if (err_chk) { - master_num--; - - tsi148_device->flush_image = - kmalloc(sizeof(struct vme_master_resource), GFP_KERNEL); - if (tsi148_device->flush_image == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "flush resource structure\n"); - retval = -ENOMEM; - goto err_master; - } - tsi148_device->flush_image->parent = tsi148_bridge; - spin_lock_init(&tsi148_device->flush_image->lock); - tsi148_device->flush_image->locked = 1; - tsi148_device->flush_image->number = master_num; - tsi148_device->flush_image->address_attr = VME_A16 | VME_A24 | - VME_A32 | VME_A64; - tsi148_device->flush_image->cycle_attr = VME_SCT | VME_BLT | - VME_MBLT | VME_2eVME | VME_2eSST | VME_2eSSTB | - VME_2eSST160 | VME_2eSST267 | VME_2eSST320 | VME_SUPER | - VME_USER | VME_PROG | VME_DATA; - tsi148_device->flush_image->width_attr = VME_D16 | VME_D32; - memset(&tsi148_device->flush_image->bus_resource, 0, - sizeof(struct resource)); - tsi148_device->flush_image->kern_base = NULL; - } - - /* Add master windows to list */ - INIT_LIST_HEAD(&tsi148_bridge->master_resources); - for (i = 0; i < master_num; i++) { - master_image = kmalloc(sizeof(struct vme_master_resource), - GFP_KERNEL); - if (master_image == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "master resource structure\n"); - retval = -ENOMEM; - goto err_master; - } - master_image->parent = tsi148_bridge; - spin_lock_init(&master_image->lock); - master_image->locked = 0; - master_image->number = i; - master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | - VME_A64; - master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | - VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 | - VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER | - VME_PROG | VME_DATA; - master_image->width_attr = VME_D16 | VME_D32; - memset(&master_image->bus_resource, 0, - sizeof(struct resource)); - master_image->kern_base = NULL; - list_add_tail(&master_image->list, - &tsi148_bridge->master_resources); - } - - /* Add slave windows to list */ - INIT_LIST_HEAD(&tsi148_bridge->slave_resources); - for (i = 0; i < TSI148_MAX_SLAVE; i++) { - slave_image = kmalloc(sizeof(struct vme_slave_resource), - GFP_KERNEL); - if (slave_image == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "slave resource structure\n"); - retval = -ENOMEM; - goto err_slave; - } - slave_image->parent = tsi148_bridge; - mutex_init(&slave_image->mtx); - slave_image->locked = 0; - slave_image->number = i; - slave_image->address_attr = VME_A16 | VME_A24 | VME_A32 | - VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 | - VME_USER3 | VME_USER4; - slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | - VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 | - VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER | - VME_PROG | VME_DATA; - list_add_tail(&slave_image->list, - &tsi148_bridge->slave_resources); - } - - /* Add dma engines to list */ - INIT_LIST_HEAD(&tsi148_bridge->dma_resources); - for (i = 0; i < TSI148_MAX_DMA; i++) { - dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), - GFP_KERNEL); - if (dma_ctrlr == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "dma resource structure\n"); - retval = -ENOMEM; - goto err_dma; - } - dma_ctrlr->parent = tsi148_bridge; - mutex_init(&dma_ctrlr->mtx); - dma_ctrlr->locked = 0; - dma_ctrlr->number = i; - dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | - VME_DMA_MEM_TO_VME | VME_DMA_VME_TO_VME | - VME_DMA_MEM_TO_MEM | VME_DMA_PATTERN_TO_VME | - VME_DMA_PATTERN_TO_MEM; - INIT_LIST_HEAD(&dma_ctrlr->pending); - INIT_LIST_HEAD(&dma_ctrlr->running); - list_add_tail(&dma_ctrlr->list, - &tsi148_bridge->dma_resources); - } - - /* Add location monitor to list */ - INIT_LIST_HEAD(&tsi148_bridge->lm_resources); - lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); - if (lm == NULL) { - dev_err(&pdev->dev, "Failed to allocate memory for " - "location monitor resource structure\n"); - retval = -ENOMEM; - goto err_lm; - } - lm->parent = tsi148_bridge; - mutex_init(&lm->mtx); - lm->locked = 0; - lm->number = 1; - lm->monitors = 4; - list_add_tail(&lm->list, &tsi148_bridge->lm_resources); - - tsi148_bridge->slave_get = tsi148_slave_get; - tsi148_bridge->slave_set = tsi148_slave_set; - tsi148_bridge->master_get = tsi148_master_get; - tsi148_bridge->master_set = tsi148_master_set; - tsi148_bridge->master_read = tsi148_master_read; - tsi148_bridge->master_write = tsi148_master_write; - tsi148_bridge->master_rmw = tsi148_master_rmw; - tsi148_bridge->dma_list_add = tsi148_dma_list_add; - tsi148_bridge->dma_list_exec = tsi148_dma_list_exec; - tsi148_bridge->dma_list_empty = tsi148_dma_list_empty; - tsi148_bridge->irq_set = tsi148_irq_set; - tsi148_bridge->irq_generate = tsi148_irq_generate; - tsi148_bridge->lm_set = tsi148_lm_set; - tsi148_bridge->lm_get = tsi148_lm_get; - tsi148_bridge->lm_attach = tsi148_lm_attach; - tsi148_bridge->lm_detach = tsi148_lm_detach; - tsi148_bridge->slot_get = tsi148_slot_get; - tsi148_bridge->alloc_consistent = tsi148_alloc_consistent; - tsi148_bridge->free_consistent = tsi148_free_consistent; - - data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); - dev_info(&pdev->dev, "Board is%s the VME system controller\n", - (data & TSI148_LCSR_VSTAT_SCONS) ? "" : " not"); - if (!geoid) - dev_info(&pdev->dev, "VME geographical address is %d\n", - data & TSI148_LCSR_VSTAT_GA_M); - else - dev_info(&pdev->dev, "VME geographical address is set to %d\n", - geoid); - - dev_info(&pdev->dev, "VME Write and flush and error check is %s\n", - err_chk ? "enabled" : "disabled"); - - if (tsi148_crcsr_init(tsi148_bridge, pdev)) { - dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); - goto err_crcsr; - } - - retval = vme_register_bridge(tsi148_bridge); - if (retval != 0) { - dev_err(&pdev->dev, "Chip Registration failed.\n"); - goto err_reg; - } - - pci_set_drvdata(pdev, tsi148_bridge); - - /* Clear VME bus "board fail", and "power-up reset" lines */ - data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); - data &= ~TSI148_LCSR_VSTAT_BRDFL; - data |= TSI148_LCSR_VSTAT_CPURST; - iowrite32be(data, tsi148_device->base + TSI148_LCSR_VSTAT); - - return 0; - -err_reg: - tsi148_crcsr_exit(tsi148_bridge, pdev); -err_crcsr: -err_lm: - /* resources are stored in link list */ - list_for_each(pos, &tsi148_bridge->lm_resources) { - lm = list_entry(pos, struct vme_lm_resource, list); - list_del(pos); - kfree(lm); - } -err_dma: - /* resources are stored in link list */ - list_for_each(pos, &tsi148_bridge->dma_resources) { - dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); - list_del(pos); - kfree(dma_ctrlr); - } -err_slave: - /* resources are stored in link list */ - list_for_each(pos, &tsi148_bridge->slave_resources) { - slave_image = list_entry(pos, struct vme_slave_resource, list); - list_del(pos); - kfree(slave_image); - } -err_master: - /* resources are stored in link list */ - list_for_each(pos, &tsi148_bridge->master_resources) { - master_image = list_entry(pos, struct vme_master_resource, - list); - list_del(pos); - kfree(master_image); - } - - tsi148_irq_exit(tsi148_bridge, pdev); -err_irq: -err_test: - iounmap(tsi148_device->base); -err_remap: - pci_release_regions(pdev); -err_resource: - pci_disable_device(pdev); -err_enable: - kfree(tsi148_device); -err_driver: - kfree(tsi148_bridge); -err_struct: - return retval; - -} - -static void tsi148_remove(struct pci_dev *pdev) -{ - struct list_head *pos = NULL; - struct list_head *tmplist; - struct vme_master_resource *master_image; - struct vme_slave_resource *slave_image; - struct vme_dma_resource *dma_ctrlr; - int i; - struct tsi148_driver *bridge; - struct vme_bridge *tsi148_bridge = pci_get_drvdata(pdev); - - bridge = tsi148_bridge->driver_priv; - - - dev_dbg(&pdev->dev, "Driver is being unloaded.\n"); - - /* - * Shutdown all inbound and outbound windows. - */ - for (i = 0; i < 8; i++) { - iowrite32be(0, bridge->base + TSI148_LCSR_IT[i] + - TSI148_LCSR_OFFSET_ITAT); - iowrite32be(0, bridge->base + TSI148_LCSR_OT[i] + - TSI148_LCSR_OFFSET_OTAT); - } - - /* - * Shutdown Location monitor. - */ - iowrite32be(0, bridge->base + TSI148_LCSR_LMAT); - - /* - * Shutdown CRG map. - */ - iowrite32be(0, bridge->base + TSI148_LCSR_CSRAT); - - /* - * Clear error status. - */ - iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_EDPAT); - iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_VEAT); - iowrite32be(0x07000700, bridge->base + TSI148_LCSR_PSTAT); - - /* - * Remove VIRQ interrupt (if any) - */ - if (ioread32be(bridge->base + TSI148_LCSR_VICR) & 0x800) - iowrite32be(0x8000, bridge->base + TSI148_LCSR_VICR); - - /* - * Map all Interrupts to PCI INTA - */ - iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM1); - iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM2); - - tsi148_irq_exit(tsi148_bridge, pdev); - - vme_unregister_bridge(tsi148_bridge); - - tsi148_crcsr_exit(tsi148_bridge, pdev); - - /* resources are stored in link list */ - list_for_each_safe(pos, tmplist, &tsi148_bridge->dma_resources) { - dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); - list_del(pos); - kfree(dma_ctrlr); - } - - /* resources are stored in link list */ - list_for_each_safe(pos, tmplist, &tsi148_bridge->slave_resources) { - slave_image = list_entry(pos, struct vme_slave_resource, list); - list_del(pos); - kfree(slave_image); - } - - /* resources are stored in link list */ - list_for_each_safe(pos, tmplist, &tsi148_bridge->master_resources) { - master_image = list_entry(pos, struct vme_master_resource, - list); - list_del(pos); - kfree(master_image); - } - - iounmap(bridge->base); - - pci_release_regions(pdev); - - pci_disable_device(pdev); - - kfree(tsi148_bridge->driver_priv); - - kfree(tsi148_bridge); -} - -static void __exit tsi148_exit(void) -{ - pci_unregister_driver(&tsi148_driver); -} - -MODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes"); -module_param(err_chk, bool, 0); - -MODULE_PARM_DESC(geoid, "Override geographical addressing"); -module_param(geoid, int, 0); - -MODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge"); -MODULE_LICENSE("GPL"); - -module_init(tsi148_init); -module_exit(tsi148_exit); diff --git a/drivers/staging/vme/bridges/vme_tsi148.h b/drivers/staging/vme/bridges/vme_tsi148.h deleted file mode 100644 index f5ed14382a8d..000000000000 --- a/drivers/staging/vme/bridges/vme_tsi148.h +++ /dev/null @@ -1,1410 +0,0 @@ -/* - * tsi148.h - * - * Support for the Tundra TSI148 VME Bridge chip - * - * Author: Tom Armistead - * Updated and maintained by Ajit Prem - * Copyright 2004 Motorola Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef TSI148_H -#define TSI148_H - -#ifndef PCI_VENDOR_ID_TUNDRA -#define PCI_VENDOR_ID_TUNDRA 0x10e3 -#endif - -#ifndef PCI_DEVICE_ID_TUNDRA_TSI148 -#define PCI_DEVICE_ID_TUNDRA_TSI148 0x148 -#endif - -/* - * Define the number of each that the Tsi148 supports. - */ -#define TSI148_MAX_MASTER 8 /* Max Master Windows */ -#define TSI148_MAX_SLAVE 8 /* Max Slave Windows */ -#define TSI148_MAX_DMA 2 /* Max DMA Controllers */ -#define TSI148_MAX_MAILBOX 4 /* Max Mail Box registers */ -#define TSI148_MAX_SEMAPHORE 8 /* Max Semaphores */ - -/* Structure used to hold driver specific information */ -struct tsi148_driver { - void __iomem *base; /* Base Address of device registers */ - wait_queue_head_t dma_queue[2]; - wait_queue_head_t iack_queue; - void (*lm_callback[4])(int); /* Called in interrupt handler */ - void *crcsr_kernel; - dma_addr_t crcsr_bus; - struct vme_master_resource *flush_image; - struct mutex vme_rmw; /* Only one RMW cycle at a time */ - struct mutex vme_int; /* - * Only one VME interrupt can be - * generated at a time, provide locking - */ -}; - -/* - * Layout of a DMAC Linked-List Descriptor - * - * Note: This structure is accessed via the chip and therefore must be - * correctly laid out - It must also be aligned on 64-bit boundaries. - */ -struct tsi148_dma_descriptor { - __be32 dsau; /* Source Address */ - __be32 dsal; - __be32 ddau; /* Destination Address */ - __be32 ddal; - __be32 dsat; /* Source attributes */ - __be32 ddat; /* Destination attributes */ - __be32 dnlau; /* Next link address */ - __be32 dnlal; - __be32 dcnt; /* Byte count */ - __be32 ddbs; /* 2eSST Broadcast select */ -}; - -struct tsi148_dma_entry { - /* - * The descriptor needs to be aligned on a 64-bit boundary, we increase - * the chance of this by putting it first in the structure. - */ - struct tsi148_dma_descriptor descriptor; - struct list_head list; - dma_addr_t dma_handle; -}; - -/* - * TSI148 ASIC register structure overlays and bit field definitions. - * - * Note: Tsi148 Register Group (CRG) consists of the following - * combination of registers: - * PCFS - PCI Configuration Space Registers - * LCSR - Local Control and Status Registers - * GCSR - Global Control and Status Registers - * CR/CSR - Subset of Configuration ROM / - * Control and Status Registers - */ - - -/* - * Command/Status Registers (CRG + $004) - */ -#define TSI148_PCFS_ID 0x0 -#define TSI148_PCFS_CSR 0x4 -#define TSI148_PCFS_CLASS 0x8 -#define TSI148_PCFS_MISC0 0xC -#define TSI148_PCFS_MBARL 0x10 -#define TSI148_PCFS_MBARU 0x14 - -#define TSI148_PCFS_SUBID 0x28 - -#define TSI148_PCFS_CAPP 0x34 - -#define TSI148_PCFS_MISC1 0x3C - -#define TSI148_PCFS_XCAPP 0x40 -#define TSI148_PCFS_XSTAT 0x44 - -/* - * LCSR definitions - */ - -/* - * Outbound Translations - */ -#define TSI148_LCSR_OT0_OTSAU 0x100 -#define TSI148_LCSR_OT0_OTSAL 0x104 -#define TSI148_LCSR_OT0_OTEAU 0x108 -#define TSI148_LCSR_OT0_OTEAL 0x10C -#define TSI148_LCSR_OT0_OTOFU 0x110 -#define TSI148_LCSR_OT0_OTOFL 0x114 -#define TSI148_LCSR_OT0_OTBS 0x118 -#define TSI148_LCSR_OT0_OTAT 0x11C - -#define TSI148_LCSR_OT1_OTSAU 0x120 -#define TSI148_LCSR_OT1_OTSAL 0x124 -#define TSI148_LCSR_OT1_OTEAU 0x128 -#define TSI148_LCSR_OT1_OTEAL 0x12C -#define TSI148_LCSR_OT1_OTOFU 0x130 -#define TSI148_LCSR_OT1_OTOFL 0x134 -#define TSI148_LCSR_OT1_OTBS 0x138 -#define TSI148_LCSR_OT1_OTAT 0x13C - -#define TSI148_LCSR_OT2_OTSAU 0x140 -#define TSI148_LCSR_OT2_OTSAL 0x144 -#define TSI148_LCSR_OT2_OTEAU 0x148 -#define TSI148_LCSR_OT2_OTEAL 0x14C -#define TSI148_LCSR_OT2_OTOFU 0x150 -#define TSI148_LCSR_OT2_OTOFL 0x154 -#define TSI148_LCSR_OT2_OTBS 0x158 -#define TSI148_LCSR_OT2_OTAT 0x15C - -#define TSI148_LCSR_OT3_OTSAU 0x160 -#define TSI148_LCSR_OT3_OTSAL 0x164 -#define TSI148_LCSR_OT3_OTEAU 0x168 -#define TSI148_LCSR_OT3_OTEAL 0x16C -#define TSI148_LCSR_OT3_OTOFU 0x170 -#define TSI148_LCSR_OT3_OTOFL 0x174 -#define TSI148_LCSR_OT3_OTBS 0x178 -#define TSI148_LCSR_OT3_OTAT 0x17C - -#define TSI148_LCSR_OT4_OTSAU 0x180 -#define TSI148_LCSR_OT4_OTSAL 0x184 -#define TSI148_LCSR_OT4_OTEAU 0x188 -#define TSI148_LCSR_OT4_OTEAL 0x18C -#define TSI148_LCSR_OT4_OTOFU 0x190 -#define TSI148_LCSR_OT4_OTOFL 0x194 -#define TSI148_LCSR_OT4_OTBS 0x198 -#define TSI148_LCSR_OT4_OTAT 0x19C - -#define TSI148_LCSR_OT5_OTSAU 0x1A0 -#define TSI148_LCSR_OT5_OTSAL 0x1A4 -#define TSI148_LCSR_OT5_OTEAU 0x1A8 -#define TSI148_LCSR_OT5_OTEAL 0x1AC -#define TSI148_LCSR_OT5_OTOFU 0x1B0 -#define TSI148_LCSR_OT5_OTOFL 0x1B4 -#define TSI148_LCSR_OT5_OTBS 0x1B8 -#define TSI148_LCSR_OT5_OTAT 0x1BC - -#define TSI148_LCSR_OT6_OTSAU 0x1C0 -#define TSI148_LCSR_OT6_OTSAL 0x1C4 -#define TSI148_LCSR_OT6_OTEAU 0x1C8 -#define TSI148_LCSR_OT6_OTEAL 0x1CC -#define TSI148_LCSR_OT6_OTOFU 0x1D0 -#define TSI148_LCSR_OT6_OTOFL 0x1D4 -#define TSI148_LCSR_OT6_OTBS 0x1D8 -#define TSI148_LCSR_OT6_OTAT 0x1DC - -#define TSI148_LCSR_OT7_OTSAU 0x1E0 -#define TSI148_LCSR_OT7_OTSAL 0x1E4 -#define TSI148_LCSR_OT7_OTEAU 0x1E8 -#define TSI148_LCSR_OT7_OTEAL 0x1EC -#define TSI148_LCSR_OT7_OTOFU 0x1F0 -#define TSI148_LCSR_OT7_OTOFL 0x1F4 -#define TSI148_LCSR_OT7_OTBS 0x1F8 -#define TSI148_LCSR_OT7_OTAT 0x1FC - -#define TSI148_LCSR_OT0 0x100 -#define TSI148_LCSR_OT1 0x120 -#define TSI148_LCSR_OT2 0x140 -#define TSI148_LCSR_OT3 0x160 -#define TSI148_LCSR_OT4 0x180 -#define TSI148_LCSR_OT5 0x1A0 -#define TSI148_LCSR_OT6 0x1C0 -#define TSI148_LCSR_OT7 0x1E0 - -static const int TSI148_LCSR_OT[8] = { TSI148_LCSR_OT0, TSI148_LCSR_OT1, - TSI148_LCSR_OT2, TSI148_LCSR_OT3, - TSI148_LCSR_OT4, TSI148_LCSR_OT5, - TSI148_LCSR_OT6, TSI148_LCSR_OT7 }; - -#define TSI148_LCSR_OFFSET_OTSAU 0x0 -#define TSI148_LCSR_OFFSET_OTSAL 0x4 -#define TSI148_LCSR_OFFSET_OTEAU 0x8 -#define TSI148_LCSR_OFFSET_OTEAL 0xC -#define TSI148_LCSR_OFFSET_OTOFU 0x10 -#define TSI148_LCSR_OFFSET_OTOFL 0x14 -#define TSI148_LCSR_OFFSET_OTBS 0x18 -#define TSI148_LCSR_OFFSET_OTAT 0x1C - -/* - * VMEbus interrupt ack - * offset 200 - */ -#define TSI148_LCSR_VIACK1 0x204 -#define TSI148_LCSR_VIACK2 0x208 -#define TSI148_LCSR_VIACK3 0x20C -#define TSI148_LCSR_VIACK4 0x210 -#define TSI148_LCSR_VIACK5 0x214 -#define TSI148_LCSR_VIACK6 0x218 -#define TSI148_LCSR_VIACK7 0x21C - -static const int TSI148_LCSR_VIACK[8] = { 0, TSI148_LCSR_VIACK1, - TSI148_LCSR_VIACK2, TSI148_LCSR_VIACK3, - TSI148_LCSR_VIACK4, TSI148_LCSR_VIACK5, - TSI148_LCSR_VIACK6, TSI148_LCSR_VIACK7 }; - -/* - * RMW - * offset 220 - */ -#define TSI148_LCSR_RMWAU 0x220 -#define TSI148_LCSR_RMWAL 0x224 -#define TSI148_LCSR_RMWEN 0x228 -#define TSI148_LCSR_RMWC 0x22C -#define TSI148_LCSR_RMWS 0x230 - -/* - * VMEbus control - * offset 234 - */ -#define TSI148_LCSR_VMCTRL 0x234 -#define TSI148_LCSR_VCTRL 0x238 -#define TSI148_LCSR_VSTAT 0x23C - -/* - * PCI status - * offset 240 - */ -#define TSI148_LCSR_PSTAT 0x240 - -/* - * VME filter. - * offset 250 - */ -#define TSI148_LCSR_VMEFL 0x250 - - /* - * VME exception. - * offset 260 - */ -#define TSI148_LCSR_VEAU 0x260 -#define TSI148_LCSR_VEAL 0x264 -#define TSI148_LCSR_VEAT 0x268 - - /* - * PCI error - * offset 270 - */ -#define TSI148_LCSR_EDPAU 0x270 -#define TSI148_LCSR_EDPAL 0x274 -#define TSI148_LCSR_EDPXA 0x278 -#define TSI148_LCSR_EDPXS 0x27C -#define TSI148_LCSR_EDPAT 0x280 - - /* - * Inbound Translations - * offset 300 - */ -#define TSI148_LCSR_IT0_ITSAU 0x300 -#define TSI148_LCSR_IT0_ITSAL 0x304 -#define TSI148_LCSR_IT0_ITEAU 0x308 -#define TSI148_LCSR_IT0_ITEAL 0x30C -#define TSI148_LCSR_IT0_ITOFU 0x310 -#define TSI148_LCSR_IT0_ITOFL 0x314 -#define TSI148_LCSR_IT0_ITAT 0x318 - -#define TSI148_LCSR_IT1_ITSAU 0x320 -#define TSI148_LCSR_IT1_ITSAL 0x324 -#define TSI148_LCSR_IT1_ITEAU 0x328 -#define TSI148_LCSR_IT1_ITEAL 0x32C -#define TSI148_LCSR_IT1_ITOFU 0x330 -#define TSI148_LCSR_IT1_ITOFL 0x334 -#define TSI148_LCSR_IT1_ITAT 0x338 - -#define TSI148_LCSR_IT2_ITSAU 0x340 -#define TSI148_LCSR_IT2_ITSAL 0x344 -#define TSI148_LCSR_IT2_ITEAU 0x348 -#define TSI148_LCSR_IT2_ITEAL 0x34C -#define TSI148_LCSR_IT2_ITOFU 0x350 -#define TSI148_LCSR_IT2_ITOFL 0x354 -#define TSI148_LCSR_IT2_ITAT 0x358 - -#define TSI148_LCSR_IT3_ITSAU 0x360 -#define TSI148_LCSR_IT3_ITSAL 0x364 -#define TSI148_LCSR_IT3_ITEAU 0x368 -#define TSI148_LCSR_IT3_ITEAL 0x36C -#define TSI148_LCSR_IT3_ITOFU 0x370 -#define TSI148_LCSR_IT3_ITOFL 0x374 -#define TSI148_LCSR_IT3_ITAT 0x378 - -#define TSI148_LCSR_IT4_ITSAU 0x380 -#define TSI148_LCSR_IT4_ITSAL 0x384 -#define TSI148_LCSR_IT4_ITEAU 0x388 -#define TSI148_LCSR_IT4_ITEAL 0x38C -#define TSI148_LCSR_IT4_ITOFU 0x390 -#define TSI148_LCSR_IT4_ITOFL 0x394 -#define TSI148_LCSR_IT4_ITAT 0x398 - -#define TSI148_LCSR_IT5_ITSAU 0x3A0 -#define TSI148_LCSR_IT5_ITSAL 0x3A4 -#define TSI148_LCSR_IT5_ITEAU 0x3A8 -#define TSI148_LCSR_IT5_ITEAL 0x3AC -#define TSI148_LCSR_IT5_ITOFU 0x3B0 -#define TSI148_LCSR_IT5_ITOFL 0x3B4 -#define TSI148_LCSR_IT5_ITAT 0x3B8 - -#define TSI148_LCSR_IT6_ITSAU 0x3C0 -#define TSI148_LCSR_IT6_ITSAL 0x3C4 -#define TSI148_LCSR_IT6_ITEAU 0x3C8 -#define TSI148_LCSR_IT6_ITEAL 0x3CC -#define TSI148_LCSR_IT6_ITOFU 0x3D0 -#define TSI148_LCSR_IT6_ITOFL 0x3D4 -#define TSI148_LCSR_IT6_ITAT 0x3D8 - -#define TSI148_LCSR_IT7_ITSAU 0x3E0 -#define TSI148_LCSR_IT7_ITSAL 0x3E4 -#define TSI148_LCSR_IT7_ITEAU 0x3E8 -#define TSI148_LCSR_IT7_ITEAL 0x3EC -#define TSI148_LCSR_IT7_ITOFU 0x3F0 -#define TSI148_LCSR_IT7_ITOFL 0x3F4 -#define TSI148_LCSR_IT7_ITAT 0x3F8 - - -#define TSI148_LCSR_IT0 0x300 -#define TSI148_LCSR_IT1 0x320 -#define TSI148_LCSR_IT2 0x340 -#define TSI148_LCSR_IT3 0x360 -#define TSI148_LCSR_IT4 0x380 -#define TSI148_LCSR_IT5 0x3A0 -#define TSI148_LCSR_IT6 0x3C0 -#define TSI148_LCSR_IT7 0x3E0 - -static const int TSI148_LCSR_IT[8] = { TSI148_LCSR_IT0, TSI148_LCSR_IT1, - TSI148_LCSR_IT2, TSI148_LCSR_IT3, - TSI148_LCSR_IT4, TSI148_LCSR_IT5, - TSI148_LCSR_IT6, TSI148_LCSR_IT7 }; - -#define TSI148_LCSR_OFFSET_ITSAU 0x0 -#define TSI148_LCSR_OFFSET_ITSAL 0x4 -#define TSI148_LCSR_OFFSET_ITEAU 0x8 -#define TSI148_LCSR_OFFSET_ITEAL 0xC -#define TSI148_LCSR_OFFSET_ITOFU 0x10 -#define TSI148_LCSR_OFFSET_ITOFL 0x14 -#define TSI148_LCSR_OFFSET_ITAT 0x18 - - /* - * Inbound Translation GCSR - * offset 400 - */ -#define TSI148_LCSR_GBAU 0x400 -#define TSI148_LCSR_GBAL 0x404 -#define TSI148_LCSR_GCSRAT 0x408 - - /* - * Inbound Translation CRG - * offset 40C - */ -#define TSI148_LCSR_CBAU 0x40C -#define TSI148_LCSR_CBAL 0x410 -#define TSI148_LCSR_CSRAT 0x414 - - /* - * Inbound Translation CR/CSR - * CRG - * offset 418 - */ -#define TSI148_LCSR_CROU 0x418 -#define TSI148_LCSR_CROL 0x41C -#define TSI148_LCSR_CRAT 0x420 - - /* - * Inbound Translation Location Monitor - * offset 424 - */ -#define TSI148_LCSR_LMBAU 0x424 -#define TSI148_LCSR_LMBAL 0x428 -#define TSI148_LCSR_LMAT 0x42C - - /* - * VMEbus Interrupt Control. - * offset 430 - */ -#define TSI148_LCSR_BCU 0x430 -#define TSI148_LCSR_BCL 0x434 -#define TSI148_LCSR_BPGTR 0x438 -#define TSI148_LCSR_BPCTR 0x43C -#define TSI148_LCSR_VICR 0x440 - - /* - * Local Bus Interrupt Control. - * offset 448 - */ -#define TSI148_LCSR_INTEN 0x448 -#define TSI148_LCSR_INTEO 0x44C -#define TSI148_LCSR_INTS 0x450 -#define TSI148_LCSR_INTC 0x454 -#define TSI148_LCSR_INTM1 0x458 -#define TSI148_LCSR_INTM2 0x45C - - /* - * DMA Controllers - * offset 500 - */ -#define TSI148_LCSR_DCTL0 0x500 -#define TSI148_LCSR_DSTA0 0x504 -#define TSI148_LCSR_DCSAU0 0x508 -#define TSI148_LCSR_DCSAL0 0x50C -#define TSI148_LCSR_DCDAU0 0x510 -#define TSI148_LCSR_DCDAL0 0x514 -#define TSI148_LCSR_DCLAU0 0x518 -#define TSI148_LCSR_DCLAL0 0x51C -#define TSI148_LCSR_DSAU0 0x520 -#define TSI148_LCSR_DSAL0 0x524 -#define TSI148_LCSR_DDAU0 0x528 -#define TSI148_LCSR_DDAL0 0x52C -#define TSI148_LCSR_DSAT0 0x530 -#define TSI148_LCSR_DDAT0 0x534 -#define TSI148_LCSR_DNLAU0 0x538 -#define TSI148_LCSR_DNLAL0 0x53C -#define TSI148_LCSR_DCNT0 0x540 -#define TSI148_LCSR_DDBS0 0x544 - -#define TSI148_LCSR_DCTL1 0x580 -#define TSI148_LCSR_DSTA1 0x584 -#define TSI148_LCSR_DCSAU1 0x588 -#define TSI148_LCSR_DCSAL1 0x58C -#define TSI148_LCSR_DCDAU1 0x590 -#define TSI148_LCSR_DCDAL1 0x594 -#define TSI148_LCSR_DCLAU1 0x598 -#define TSI148_LCSR_DCLAL1 0x59C -#define TSI148_LCSR_DSAU1 0x5A0 -#define TSI148_LCSR_DSAL1 0x5A4 -#define TSI148_LCSR_DDAU1 0x5A8 -#define TSI148_LCSR_DDAL1 0x5AC -#define TSI148_LCSR_DSAT1 0x5B0 -#define TSI148_LCSR_DDAT1 0x5B4 -#define TSI148_LCSR_DNLAU1 0x5B8 -#define TSI148_LCSR_DNLAL1 0x5BC -#define TSI148_LCSR_DCNT1 0x5C0 -#define TSI148_LCSR_DDBS1 0x5C4 - -#define TSI148_LCSR_DMA0 0x500 -#define TSI148_LCSR_DMA1 0x580 - - -static const int TSI148_LCSR_DMA[TSI148_MAX_DMA] = { TSI148_LCSR_DMA0, - TSI148_LCSR_DMA1 }; - -#define TSI148_LCSR_OFFSET_DCTL 0x0 -#define TSI148_LCSR_OFFSET_DSTA 0x4 -#define TSI148_LCSR_OFFSET_DCSAU 0x8 -#define TSI148_LCSR_OFFSET_DCSAL 0xC -#define TSI148_LCSR_OFFSET_DCDAU 0x10 -#define TSI148_LCSR_OFFSET_DCDAL 0x14 -#define TSI148_LCSR_OFFSET_DCLAU 0x18 -#define TSI148_LCSR_OFFSET_DCLAL 0x1C -#define TSI148_LCSR_OFFSET_DSAU 0x20 -#define TSI148_LCSR_OFFSET_DSAL 0x24 -#define TSI148_LCSR_OFFSET_DDAU 0x28 -#define TSI148_LCSR_OFFSET_DDAL 0x2C -#define TSI148_LCSR_OFFSET_DSAT 0x30 -#define TSI148_LCSR_OFFSET_DDAT 0x34 -#define TSI148_LCSR_OFFSET_DNLAU 0x38 -#define TSI148_LCSR_OFFSET_DNLAL 0x3C -#define TSI148_LCSR_OFFSET_DCNT 0x40 -#define TSI148_LCSR_OFFSET_DDBS 0x44 - - /* - * GCSR Register Group - */ - - /* - * GCSR CRG - * offset 00 600 - DEVI/VENI - * offset 04 604 - CTRL/GA/REVID - * offset 08 608 - Semaphore3/2/1/0 - * offset 0C 60C - Seamphore7/6/5/4 - */ -#define TSI148_GCSR_ID 0x600 -#define TSI148_GCSR_CSR 0x604 -#define TSI148_GCSR_SEMA0 0x608 -#define TSI148_GCSR_SEMA1 0x60C - - /* - * Mail Box - * GCSR CRG - * offset 10 610 - Mailbox0 - */ -#define TSI148_GCSR_MBOX0 0x610 -#define TSI148_GCSR_MBOX1 0x614 -#define TSI148_GCSR_MBOX2 0x618 -#define TSI148_GCSR_MBOX3 0x61C - -static const int TSI148_GCSR_MBOX[4] = { TSI148_GCSR_MBOX0, - TSI148_GCSR_MBOX1, - TSI148_GCSR_MBOX2, - TSI148_GCSR_MBOX3 }; - - /* - * CR/CSR - */ - - /* - * CR/CSR CRG - * offset 7FFF4 FF4 - CSRBCR - * offset 7FFF8 FF8 - CSRBSR - * offset 7FFFC FFC - CBAR - */ -#define TSI148_CSRBCR 0xFF4 -#define TSI148_CSRBSR 0xFF8 -#define TSI148_CBAR 0xFFC - - - - - /* - * TSI148 Register Bit Definitions - */ - - /* - * PFCS Register Set - */ -#define TSI148_PCFS_CMMD_SERR (1<<8) /* SERR_L out pin ssys err */ -#define TSI148_PCFS_CMMD_PERR (1<<6) /* PERR_L out pin parity */ -#define TSI148_PCFS_CMMD_MSTR (1<<2) /* PCI bus master */ -#define TSI148_PCFS_CMMD_MEMSP (1<<1) /* PCI mem space access */ -#define TSI148_PCFS_CMMD_IOSP (1<<0) /* PCI I/O space enable */ - -#define TSI148_PCFS_STAT_RCPVE (1<<15) /* Detected Parity Error */ -#define TSI148_PCFS_STAT_SIGSE (1<<14) /* Signalled System Error */ -#define TSI148_PCFS_STAT_RCVMA (1<<13) /* Received Master Abort */ -#define TSI148_PCFS_STAT_RCVTA (1<<12) /* Received Target Abort */ -#define TSI148_PCFS_STAT_SIGTA (1<<11) /* Signalled Target Abort */ -#define TSI148_PCFS_STAT_SELTIM (3<<9) /* DELSEL Timing */ -#define TSI148_PCFS_STAT_DPAR (1<<8) /* Data Parity Err Reported */ -#define TSI148_PCFS_STAT_FAST (1<<7) /* Fast back-to-back Cap */ -#define TSI148_PCFS_STAT_P66M (1<<5) /* 66 MHz Capable */ -#define TSI148_PCFS_STAT_CAPL (1<<4) /* Capab List - address $34 */ - -/* - * Revision ID/Class Code Registers (CRG +$008) - */ -#define TSI148_PCFS_CLAS_M (0xFF<<24) /* Class ID */ -#define TSI148_PCFS_SUBCLAS_M (0xFF<<16) /* Sub-Class ID */ -#define TSI148_PCFS_PROGIF_M (0xFF<<8) /* Sub-Class ID */ -#define TSI148_PCFS_REVID_M (0xFF<<0) /* Rev ID */ - -/* - * Cache Line Size/ Master Latency Timer/ Header Type Registers (CRG + $00C) - */ -#define TSI148_PCFS_HEAD_M (0xFF<<16) /* Master Lat Timer */ -#define TSI148_PCFS_MLAT_M (0xFF<<8) /* Master Lat Timer */ -#define TSI148_PCFS_CLSZ_M (0xFF<<0) /* Cache Line Size */ - -/* - * Memory Base Address Lower Reg (CRG + $010) - */ -#define TSI148_PCFS_MBARL_BASEL_M (0xFFFFF<<12) /* Base Addr Lower Mask */ -#define TSI148_PCFS_MBARL_PRE (1<<3) /* Prefetch */ -#define TSI148_PCFS_MBARL_MTYPE_M (3<<1) /* Memory Type Mask */ -#define TSI148_PCFS_MBARL_IOMEM (1<<0) /* I/O Space Indicator */ - -/* - * Message Signaled Interrupt Capabilities Register (CRG + $040) - */ -#define TSI148_PCFS_MSICAP_64BAC (1<<7) /* 64-bit Address Capable */ -#define TSI148_PCFS_MSICAP_MME_M (7<<4) /* Multiple Msg Enable Mask */ -#define TSI148_PCFS_MSICAP_MMC_M (7<<1) /* Multiple Msg Capable Mask */ -#define TSI148_PCFS_MSICAP_MSIEN (1<<0) /* Msg signaled INT Enable */ - -/* - * Message Address Lower Register (CRG +$044) - */ -#define TSI148_PCFS_MSIAL_M (0x3FFFFFFF<<2) /* Mask */ - -/* - * Message Data Register (CRG + 4C) - */ -#define TSI148_PCFS_MSIMD_M (0xFFFF<<0) /* Mask */ - -/* - * PCI-X Capabilities Register (CRG + $050) - */ -#define TSI148_PCFS_PCIXCAP_MOST_M (7<<4) /* Max outstanding Split Tran */ -#define TSI148_PCFS_PCIXCAP_MMRBC_M (3<<2) /* Max Mem Read byte cnt */ -#define TSI148_PCFS_PCIXCAP_ERO (1<<1) /* Enable Relaxed Ordering */ -#define TSI148_PCFS_PCIXCAP_DPERE (1<<0) /* Data Parity Recover Enable */ - -/* - * PCI-X Status Register (CRG +$054) - */ -#define TSI148_PCFS_PCIXSTAT_RSCEM (1<<29) /* Received Split Comp Error */ -#define TSI148_PCFS_PCIXSTAT_DMCRS_M (7<<26) /* max Cumulative Read Size */ -#define TSI148_PCFS_PCIXSTAT_DMOST_M (7<<23) /* max outstanding Split Trans - */ -#define TSI148_PCFS_PCIXSTAT_DMMRC_M (3<<21) /* max mem read byte count */ -#define TSI148_PCFS_PCIXSTAT_DC (1<<20) /* Device Complexity */ -#define TSI148_PCFS_PCIXSTAT_USC (1<<19) /* Unexpected Split comp */ -#define TSI148_PCFS_PCIXSTAT_SCD (1<<18) /* Split completion discard */ -#define TSI148_PCFS_PCIXSTAT_133C (1<<17) /* 133MHz capable */ -#define TSI148_PCFS_PCIXSTAT_64D (1<<16) /* 64 bit device */ -#define TSI148_PCFS_PCIXSTAT_BN_M (0xFF<<8) /* Bus number */ -#define TSI148_PCFS_PCIXSTAT_DN_M (0x1F<<3) /* Device number */ -#define TSI148_PCFS_PCIXSTAT_FN_M (7<<0) /* Function Number */ - -/* - * LCSR Registers - */ - -/* - * Outbound Translation Starting Address Lower - */ -#define TSI148_LCSR_OTSAL_M (0xFFFF<<16) /* Mask */ - -/* - * Outbound Translation Ending Address Lower - */ -#define TSI148_LCSR_OTEAL_M (0xFFFF<<16) /* Mask */ - -/* - * Outbound Translation Offset Lower - */ -#define TSI148_LCSR_OTOFFL_M (0xFFFF<<16) /* Mask */ - -/* - * Outbound Translation 2eSST Broadcast Select - */ -#define TSI148_LCSR_OTBS_M (0xFFFFF<<0) /* Mask */ - -/* - * Outbound Translation Attribute - */ -#define TSI148_LCSR_OTAT_EN (1<<31) /* Window Enable */ -#define TSI148_LCSR_OTAT_MRPFD (1<<18) /* Prefetch Disable */ - -#define TSI148_LCSR_OTAT_PFS_M (3<<16) /* Prefetch Size Mask */ -#define TSI148_LCSR_OTAT_PFS_2 (0<<16) /* 2 Cache Lines P Size */ -#define TSI148_LCSR_OTAT_PFS_4 (1<<16) /* 4 Cache Lines P Size */ -#define TSI148_LCSR_OTAT_PFS_8 (2<<16) /* 8 Cache Lines P Size */ -#define TSI148_LCSR_OTAT_PFS_16 (3<<16) /* 16 Cache Lines P Size */ - -#define TSI148_LCSR_OTAT_2eSSTM_M (7<<11) /* 2eSST Xfer Rate Mask */ -#define TSI148_LCSR_OTAT_2eSSTM_160 (0<<11) /* 160MB/s 2eSST Xfer Rate */ -#define TSI148_LCSR_OTAT_2eSSTM_267 (1<<11) /* 267MB/s 2eSST Xfer Rate */ -#define TSI148_LCSR_OTAT_2eSSTM_320 (2<<11) /* 320MB/s 2eSST Xfer Rate */ - -#define TSI148_LCSR_OTAT_TM_M (7<<8) /* Xfer Protocol Mask */ -#define TSI148_LCSR_OTAT_TM_SCT (0<<8) /* SCT Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_BLT (1<<8) /* BLT Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_MBLT (2<<8) /* MBLT Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_2eVME (3<<8) /* 2eVME Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_2eSST (4<<8) /* 2eSST Xfer Protocol */ -#define TSI148_LCSR_OTAT_TM_2eSSTB (5<<8) /* 2eSST Bcast Xfer Protocol */ - -#define TSI148_LCSR_OTAT_DBW_M (3<<6) /* Max Data Width */ -#define TSI148_LCSR_OTAT_DBW_16 (0<<6) /* 16-bit Data Width */ -#define TSI148_LCSR_OTAT_DBW_32 (1<<6) /* 32-bit Data Width */ - -#define TSI148_LCSR_OTAT_SUP (1<<5) /* Supervisory Access */ -#define TSI148_LCSR_OTAT_PGM (1<<4) /* Program Access */ - -#define TSI148_LCSR_OTAT_AMODE_M (0xf<<0) /* Address Mode Mask */ -#define TSI148_LCSR_OTAT_AMODE_A16 (0<<0) /* A16 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_A24 (1<<0) /* A24 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_A32 (2<<0) /* A32 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_A64 (4<<0) /* A32 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_CRCSR (5<<0) /* CR/CSR Address Space */ -#define TSI148_LCSR_OTAT_AMODE_USER1 (8<<0) /* User1 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_USER2 (9<<0) /* User2 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_USER3 (10<<0) /* User3 Address Space */ -#define TSI148_LCSR_OTAT_AMODE_USER4 (11<<0) /* User4 Address Space */ - -/* - * VME Master Control Register CRG+$234 - */ -#define TSI148_LCSR_VMCTRL_VSA (1<<27) /* VMEbus Stop Ack */ -#define TSI148_LCSR_VMCTRL_VS (1<<26) /* VMEbus Stop */ -#define TSI148_LCSR_VMCTRL_DHB (1<<25) /* Device Has Bus */ -#define TSI148_LCSR_VMCTRL_DWB (1<<24) /* Device Wants Bus */ - -#define TSI148_LCSR_VMCTRL_RMWEN (1<<20) /* RMW Enable */ - -#define TSI148_LCSR_VMCTRL_ATO_M (7<<16) /* Master Access Time-out Mask - */ -#define TSI148_LCSR_VMCTRL_ATO_32 (0<<16) /* 32 us */ -#define TSI148_LCSR_VMCTRL_ATO_128 (1<<16) /* 128 us */ -#define TSI148_LCSR_VMCTRL_ATO_512 (2<<16) /* 512 us */ -#define TSI148_LCSR_VMCTRL_ATO_2M (3<<16) /* 2 ms */ -#define TSI148_LCSR_VMCTRL_ATO_8M (4<<16) /* 8 ms */ -#define TSI148_LCSR_VMCTRL_ATO_32M (5<<16) /* 32 ms */ -#define TSI148_LCSR_VMCTRL_ATO_128M (6<<16) /* 128 ms */ -#define TSI148_LCSR_VMCTRL_ATO_DIS (7<<16) /* Disabled */ - -#define TSI148_LCSR_VMCTRL_VTOFF_M (7<<12) /* VMEbus Master Time off */ -#define TSI148_LCSR_VMCTRL_VTOFF_0 (0<<12) /* 0us */ -#define TSI148_LCSR_VMCTRL_VTOFF_1 (1<<12) /* 1us */ -#define TSI148_LCSR_VMCTRL_VTOFF_2 (2<<12) /* 2us */ -#define TSI148_LCSR_VMCTRL_VTOFF_4 (3<<12) /* 4us */ -#define TSI148_LCSR_VMCTRL_VTOFF_8 (4<<12) /* 8us */ -#define TSI148_LCSR_VMCTRL_VTOFF_16 (5<<12) /* 16us */ -#define TSI148_LCSR_VMCTRL_VTOFF_32 (6<<12) /* 32us */ -#define TSI148_LCSR_VMCTRL_VTOFF_64 (7<<12) /* 64us */ - -#define TSI148_LCSR_VMCTRL_VTON_M (7<<8) /* VMEbus Master Time On */ -#define TSI148_LCSR_VMCTRL_VTON_4 (0<<8) /* 8us */ -#define TSI148_LCSR_VMCTRL_VTON_8 (1<<8) /* 8us */ -#define TSI148_LCSR_VMCTRL_VTON_16 (2<<8) /* 16us */ -#define TSI148_LCSR_VMCTRL_VTON_32 (3<<8) /* 32us */ -#define TSI148_LCSR_VMCTRL_VTON_64 (4<<8) /* 64us */ -#define TSI148_LCSR_VMCTRL_VTON_128 (5<<8) /* 128us */ -#define TSI148_LCSR_VMCTRL_VTON_256 (6<<8) /* 256us */ -#define TSI148_LCSR_VMCTRL_VTON_512 (7<<8) /* 512us */ - -#define TSI148_LCSR_VMCTRL_VREL_M (3<<3) /* VMEbus Master Rel Mode Mask - */ -#define TSI148_LCSR_VMCTRL_VREL_T_D (0<<3) /* Time on or Done */ -#define TSI148_LCSR_VMCTRL_VREL_T_R_D (1<<3) /* Time on and REQ or Done */ -#define TSI148_LCSR_VMCTRL_VREL_T_B_D (2<<3) /* Time on and BCLR or Done */ -#define TSI148_LCSR_VMCTRL_VREL_T_D_R (3<<3) /* Time on or Done and REQ */ - -#define TSI148_LCSR_VMCTRL_VFAIR (1<<2) /* VMEbus Master Fair Mode */ -#define TSI148_LCSR_VMCTRL_VREQL_M (3<<0) /* VMEbus Master Req Level Mask - */ - -/* - * VMEbus Control Register CRG+$238 - */ -#define TSI148_LCSR_VCTRL_LRE (1<<31) /* Late Retry Enable */ - -#define TSI148_LCSR_VCTRL_DLT_M (0xF<<24) /* Deadlock Timer */ -#define TSI148_LCSR_VCTRL_DLT_OFF (0<<24) /* Deadlock Timer Off */ -#define TSI148_LCSR_VCTRL_DLT_16 (1<<24) /* 16 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_32 (2<<24) /* 32 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_64 (3<<24) /* 64 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_128 (4<<24) /* 128 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_256 (5<<24) /* 256 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_512 (6<<24) /* 512 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_1024 (7<<24) /* 1024 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_2048 (8<<24) /* 2048 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_4096 (9<<24) /* 4096 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_8192 (0xA<<24) /* 8192 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_16384 (0xB<<24) /* 16384 VCLKS */ -#define TSI148_LCSR_VCTRL_DLT_32768 (0xC<<24) /* 32768 VCLKS */ - -#define TSI148_LCSR_VCTRL_NERBB (1<<20) /* No Early Release of Bus Busy - */ - -#define TSI148_LCSR_VCTRL_SRESET (1<<17) /* System Reset */ -#define TSI148_LCSR_VCTRL_LRESET (1<<16) /* Local Reset */ - -#define TSI148_LCSR_VCTRL_SFAILAI (1<<15) /* SYSFAIL Auto Slot ID */ -#define TSI148_LCSR_VCTRL_BID_M (0x1F<<8) /* Broadcast ID Mask */ - -#define TSI148_LCSR_VCTRL_ATOEN (1<<7) /* Arbiter Time-out Enable */ -#define TSI148_LCSR_VCTRL_ROBIN (1<<6) /* VMEbus Round Robin */ - -#define TSI148_LCSR_VCTRL_GTO_M (7<<0) /* VMEbus Global Time-out Mask - */ -#define TSI148_LCSR_VCTRL_GTO_8 (0<<0) /* 8 us */ -#define TSI148_LCSR_VCTRL_GTO_16 (1<<0) /* 16 us */ -#define TSI148_LCSR_VCTRL_GTO_32 (2<<0) /* 32 us */ -#define TSI148_LCSR_VCTRL_GTO_64 (3<<0) /* 64 us */ -#define TSI148_LCSR_VCTRL_GTO_128 (4<<0) /* 128 us */ -#define TSI148_LCSR_VCTRL_GTO_256 (5<<0) /* 256 us */ -#define TSI148_LCSR_VCTRL_GTO_512 (6<<0) /* 512 us */ -#define TSI148_LCSR_VCTRL_GTO_DIS (7<<0) /* Disabled */ - -/* - * VMEbus Status Register CRG + $23C - */ -#define TSI148_LCSR_VSTAT_CPURST (1<<15) /* Clear power up reset */ -#define TSI148_LCSR_VSTAT_BRDFL (1<<14) /* Board fail */ -#define TSI148_LCSR_VSTAT_PURSTS (1<<12) /* Power up reset status */ -#define TSI148_LCSR_VSTAT_BDFAILS (1<<11) /* Board Fail Status */ -#define TSI148_LCSR_VSTAT_SYSFAILS (1<<10) /* System Fail Status */ -#define TSI148_LCSR_VSTAT_ACFAILS (1<<9) /* AC fail status */ -#define TSI148_LCSR_VSTAT_SCONS (1<<8) /* System Cont Status */ -#define TSI148_LCSR_VSTAT_GAP (1<<5) /* Geographic Addr Parity */ -#define TSI148_LCSR_VSTAT_GA_M (0x1F<<0) /* Geographic Addr Mask */ - -/* - * PCI Configuration Status Register CRG+$240 - */ -#define TSI148_LCSR_PSTAT_REQ64S (1<<6) /* Request 64 status set */ -#define TSI148_LCSR_PSTAT_M66ENS (1<<5) /* M66ENS 66Mhz enable */ -#define TSI148_LCSR_PSTAT_FRAMES (1<<4) /* Frame Status */ -#define TSI148_LCSR_PSTAT_IRDYS (1<<3) /* IRDY status */ -#define TSI148_LCSR_PSTAT_DEVSELS (1<<2) /* DEVL status */ -#define TSI148_LCSR_PSTAT_STOPS (1<<1) /* STOP status */ -#define TSI148_LCSR_PSTAT_TRDYS (1<<0) /* TRDY status */ - -/* - * VMEbus Exception Attributes Register CRG + $268 - */ -#define TSI148_LCSR_VEAT_VES (1<<31) /* Status */ -#define TSI148_LCSR_VEAT_VEOF (1<<30) /* Overflow */ -#define TSI148_LCSR_VEAT_VESCL (1<<29) /* Status Clear */ -#define TSI148_LCSR_VEAT_2EOT (1<<21) /* 2e Odd Termination */ -#define TSI148_LCSR_VEAT_2EST (1<<20) /* 2e Slave terminated */ -#define TSI148_LCSR_VEAT_BERR (1<<19) /* Bus Error */ -#define TSI148_LCSR_VEAT_LWORD (1<<18) /* LWORD_ signal state */ -#define TSI148_LCSR_VEAT_WRITE (1<<17) /* WRITE_ signal state */ -#define TSI148_LCSR_VEAT_IACK (1<<16) /* IACK_ signal state */ -#define TSI148_LCSR_VEAT_DS1 (1<<15) /* DS1_ signal state */ -#define TSI148_LCSR_VEAT_DS0 (1<<14) /* DS0_ signal state */ -#define TSI148_LCSR_VEAT_AM_M (0x3F<<8) /* Address Mode Mask */ -#define TSI148_LCSR_VEAT_XAM_M (0xFF<<0) /* Master AMode Mask */ - - -/* - * VMEbus PCI Error Diagnostics PCI/X Attributes Register CRG + $280 - */ -#define TSI148_LCSR_EDPAT_EDPCL (1<<29) - -/* - * Inbound Translation Starting Address Lower - */ -#define TSI148_LCSR_ITSAL6432_M (0xFFFF<<16) /* Mask */ -#define TSI148_LCSR_ITSAL24_M (0x00FFF<<12) /* Mask */ -#define TSI148_LCSR_ITSAL16_M (0x0000FFF<<4) /* Mask */ - -/* - * Inbound Translation Ending Address Lower - */ -#define TSI148_LCSR_ITEAL6432_M (0xFFFF<<16) /* Mask */ -#define TSI148_LCSR_ITEAL24_M (0x00FFF<<12) /* Mask */ -#define TSI148_LCSR_ITEAL16_M (0x0000FFF<<4) /* Mask */ - -/* - * Inbound Translation Offset Lower - */ -#define TSI148_LCSR_ITOFFL6432_M (0xFFFF<<16) /* Mask */ -#define TSI148_LCSR_ITOFFL24_M (0xFFFFF<<12) /* Mask */ -#define TSI148_LCSR_ITOFFL16_M (0xFFFFFFF<<4) /* Mask */ - -/* - * Inbound Translation Attribute - */ -#define TSI148_LCSR_ITAT_EN (1<<31) /* Window Enable */ -#define TSI148_LCSR_ITAT_TH (1<<18) /* Prefetch Threshold */ - -#define TSI148_LCSR_ITAT_VFS_M (3<<16) /* Virtual FIFO Size Mask */ -#define TSI148_LCSR_ITAT_VFS_64 (0<<16) /* 64 bytes Virtual FIFO Size */ -#define TSI148_LCSR_ITAT_VFS_128 (1<<16) /* 128 bytes Virtual FIFO Sz */ -#define TSI148_LCSR_ITAT_VFS_256 (2<<16) /* 256 bytes Virtual FIFO Sz */ -#define TSI148_LCSR_ITAT_VFS_512 (3<<16) /* 512 bytes Virtual FIFO Sz */ - -#define TSI148_LCSR_ITAT_2eSSTM_M (7<<12) /* 2eSST Xfer Rate Mask */ -#define TSI148_LCSR_ITAT_2eSSTM_160 (0<<12) /* 160MB/s 2eSST Xfer Rate */ -#define TSI148_LCSR_ITAT_2eSSTM_267 (1<<12) /* 267MB/s 2eSST Xfer Rate */ -#define TSI148_LCSR_ITAT_2eSSTM_320 (2<<12) /* 320MB/s 2eSST Xfer Rate */ - -#define TSI148_LCSR_ITAT_2eSSTB (1<<11) /* 2eSST Bcast Xfer Protocol */ -#define TSI148_LCSR_ITAT_2eSST (1<<10) /* 2eSST Xfer Protocol */ -#define TSI148_LCSR_ITAT_2eVME (1<<9) /* 2eVME Xfer Protocol */ -#define TSI148_LCSR_ITAT_MBLT (1<<8) /* MBLT Xfer Protocol */ -#define TSI148_LCSR_ITAT_BLT (1<<7) /* BLT Xfer Protocol */ - -#define TSI148_LCSR_ITAT_AS_M (7<<4) /* Address Space Mask */ -#define TSI148_LCSR_ITAT_AS_A16 (0<<4) /* A16 Address Space */ -#define TSI148_LCSR_ITAT_AS_A24 (1<<4) /* A24 Address Space */ -#define TSI148_LCSR_ITAT_AS_A32 (2<<4) /* A32 Address Space */ -#define TSI148_LCSR_ITAT_AS_A64 (4<<4) /* A64 Address Space */ - -#define TSI148_LCSR_ITAT_SUPR (1<<3) /* Supervisor Access */ -#define TSI148_LCSR_ITAT_NPRIV (1<<2) /* Non-Priv (User) Access */ -#define TSI148_LCSR_ITAT_PGM (1<<1) /* Program Access */ -#define TSI148_LCSR_ITAT_DATA (1<<0) /* Data Access */ - -/* - * GCSR Base Address Lower Address CRG +$404 - */ -#define TSI148_LCSR_GBAL_M (0x7FFFFFF<<5) /* Mask */ - -/* - * GCSR Attribute Register CRG + $408 - */ -#define TSI148_LCSR_GCSRAT_EN (1<<7) /* Enable access to GCSR */ - -#define TSI148_LCSR_GCSRAT_AS_M (7<<4) /* Address Space Mask */ -#define TSI148_LCSR_GCSRAT_AS_A16 (0<<4) /* Address Space 16 */ -#define TSI148_LCSR_GCSRAT_AS_A24 (1<<4) /* Address Space 24 */ -#define TSI148_LCSR_GCSRAT_AS_A32 (2<<4) /* Address Space 32 */ -#define TSI148_LCSR_GCSRAT_AS_A64 (4<<4) /* Address Space 64 */ - -#define TSI148_LCSR_GCSRAT_SUPR (1<<3) /* Sup set -GCSR decoder */ -#define TSI148_LCSR_GCSRAT_NPRIV (1<<2) /* Non-Privliged set - CGSR */ -#define TSI148_LCSR_GCSRAT_PGM (1<<1) /* Program set - GCSR decoder */ -#define TSI148_LCSR_GCSRAT_DATA (1<<0) /* DATA set GCSR decoder */ - -/* - * CRG Base Address Lower Address CRG + $410 - */ -#define TSI148_LCSR_CBAL_M (0xFFFFF<<12) - -/* - * CRG Attribute Register CRG + $414 - */ -#define TSI148_LCSR_CRGAT_EN (1<<7) /* Enable PRG Access */ - -#define TSI148_LCSR_CRGAT_AS_M (7<<4) /* Address Space */ -#define TSI148_LCSR_CRGAT_AS_A16 (0<<4) /* Address Space 16 */ -#define TSI148_LCSR_CRGAT_AS_A24 (1<<4) /* Address Space 24 */ -#define TSI148_LCSR_CRGAT_AS_A32 (2<<4) /* Address Space 32 */ -#define TSI148_LCSR_CRGAT_AS_A64 (4<<4) /* Address Space 64 */ - -#define TSI148_LCSR_CRGAT_SUPR (1<<3) /* Supervisor Access */ -#define TSI148_LCSR_CRGAT_NPRIV (1<<2) /* Non-Privliged(User) Access */ -#define TSI148_LCSR_CRGAT_PGM (1<<1) /* Program Access */ -#define TSI148_LCSR_CRGAT_DATA (1<<0) /* Data Access */ - -/* - * CR/CSR Offset Lower Register CRG + $41C - */ -#define TSI148_LCSR_CROL_M (0x1FFF<<19) /* Mask */ - -/* - * CR/CSR Attribute register CRG + $420 - */ -#define TSI148_LCSR_CRAT_EN (1<<7) /* Enable access to CR/CSR */ - -/* - * Location Monitor base address lower register CRG + $428 - */ -#define TSI148_LCSR_LMBAL_M (0x7FFFFFF<<5) /* Mask */ - -/* - * Location Monitor Attribute Register CRG + $42C - */ -#define TSI148_LCSR_LMAT_EN (1<<7) /* Enable Location Monitor */ - -#define TSI148_LCSR_LMAT_AS_M (7<<4) /* Address Space MASK */ -#define TSI148_LCSR_LMAT_AS_A16 (0<<4) /* A16 */ -#define TSI148_LCSR_LMAT_AS_A24 (1<<4) /* A24 */ -#define TSI148_LCSR_LMAT_AS_A32 (2<<4) /* A32 */ -#define TSI148_LCSR_LMAT_AS_A64 (4<<4) /* A64 */ - -#define TSI148_LCSR_LMAT_SUPR (1<<3) /* Supervisor Access */ -#define TSI148_LCSR_LMAT_NPRIV (1<<2) /* Non-Priv (User) Access */ -#define TSI148_LCSR_LMAT_PGM (1<<1) /* Program Access */ -#define TSI148_LCSR_LMAT_DATA (1<<0) /* Data Access */ - -/* - * Broadcast Pulse Generator Timer Register CRG + $438 - */ -#define TSI148_LCSR_BPGTR_BPGT_M (0xFFFF<<0) /* Mask */ - -/* - * Broadcast Programmable Clock Timer Register CRG + $43C - */ -#define TSI148_LCSR_BPCTR_BPCT_M (0xFFFFFF<<0) /* Mask */ - -/* - * VMEbus Interrupt Control Register CRG + $43C - */ -#define TSI148_LCSR_VICR_CNTS_M (3<<22) /* Cntr Source MASK */ -#define TSI148_LCSR_VICR_CNTS_DIS (1<<22) /* Cntr Disable */ -#define TSI148_LCSR_VICR_CNTS_IRQ1 (2<<22) /* IRQ1 to Cntr */ -#define TSI148_LCSR_VICR_CNTS_IRQ2 (3<<22) /* IRQ2 to Cntr */ - -#define TSI148_LCSR_VICR_EDGIS_M (3<<20) /* Edge interrupt MASK */ -#define TSI148_LCSR_VICR_EDGIS_DIS (1<<20) /* Edge interrupt Disable */ -#define TSI148_LCSR_VICR_EDGIS_IRQ1 (2<<20) /* IRQ1 to Edge */ -#define TSI148_LCSR_VICR_EDGIS_IRQ2 (3<<20) /* IRQ2 to Edge */ - -#define TSI148_LCSR_VICR_IRQIF_M (3<<18) /* IRQ1* Function MASK */ -#define TSI148_LCSR_VICR_IRQIF_NORM (1<<18) /* Normal */ -#define TSI148_LCSR_VICR_IRQIF_PULSE (2<<18) /* Pulse Generator */ -#define TSI148_LCSR_VICR_IRQIF_PROG (3<<18) /* Programmable Clock */ -#define TSI148_LCSR_VICR_IRQIF_1U (4<<18) /* 1us Clock */ - -#define TSI148_LCSR_VICR_IRQ2F_M (3<<16) /* IRQ2* Function MASK */ -#define TSI148_LCSR_VICR_IRQ2F_NORM (1<<16) /* Normal */ -#define TSI148_LCSR_VICR_IRQ2F_PULSE (2<<16) /* Pulse Generator */ -#define TSI148_LCSR_VICR_IRQ2F_PROG (3<<16) /* Programmable Clock */ -#define TSI148_LCSR_VICR_IRQ2F_1U (4<<16) /* 1us Clock */ - -#define TSI148_LCSR_VICR_BIP (1<<15) /* Broadcast Interrupt Pulse */ - -#define TSI148_LCSR_VICR_IRQC (1<<12) /* VMEbus IRQ Clear */ -#define TSI148_LCSR_VICR_IRQS (1<<11) /* VMEbus IRQ Status */ - -#define TSI148_LCSR_VICR_IRQL_M (7<<8) /* VMEbus SW IRQ Level Mask */ -#define TSI148_LCSR_VICR_IRQL_1 (1<<8) /* VMEbus SW IRQ Level 1 */ -#define TSI148_LCSR_VICR_IRQL_2 (2<<8) /* VMEbus SW IRQ Level 2 */ -#define TSI148_LCSR_VICR_IRQL_3 (3<<8) /* VMEbus SW IRQ Level 3 */ -#define TSI148_LCSR_VICR_IRQL_4 (4<<8) /* VMEbus SW IRQ Level 4 */ -#define TSI148_LCSR_VICR_IRQL_5 (5<<8) /* VMEbus SW IRQ Level 5 */ -#define TSI148_LCSR_VICR_IRQL_6 (6<<8) /* VMEbus SW IRQ Level 6 */ -#define TSI148_LCSR_VICR_IRQL_7 (7<<8) /* VMEbus SW IRQ Level 7 */ - -static const int TSI148_LCSR_VICR_IRQL[8] = { 0, TSI148_LCSR_VICR_IRQL_1, - TSI148_LCSR_VICR_IRQL_2, TSI148_LCSR_VICR_IRQL_3, - TSI148_LCSR_VICR_IRQL_4, TSI148_LCSR_VICR_IRQL_5, - TSI148_LCSR_VICR_IRQL_6, TSI148_LCSR_VICR_IRQL_7 }; - -#define TSI148_LCSR_VICR_STID_M (0xFF<<0) /* Status/ID Mask */ - -/* - * Interrupt Enable Register CRG + $440 - */ -#define TSI148_LCSR_INTEN_DMA1EN (1<<25) /* DMAC 1 */ -#define TSI148_LCSR_INTEN_DMA0EN (1<<24) /* DMAC 0 */ -#define TSI148_LCSR_INTEN_LM3EN (1<<23) /* Location Monitor 3 */ -#define TSI148_LCSR_INTEN_LM2EN (1<<22) /* Location Monitor 2 */ -#define TSI148_LCSR_INTEN_LM1EN (1<<21) /* Location Monitor 1 */ -#define TSI148_LCSR_INTEN_LM0EN (1<<20) /* Location Monitor 0 */ -#define TSI148_LCSR_INTEN_MB3EN (1<<19) /* Mail Box 3 */ -#define TSI148_LCSR_INTEN_MB2EN (1<<18) /* Mail Box 2 */ -#define TSI148_LCSR_INTEN_MB1EN (1<<17) /* Mail Box 1 */ -#define TSI148_LCSR_INTEN_MB0EN (1<<16) /* Mail Box 0 */ -#define TSI148_LCSR_INTEN_PERREN (1<<13) /* PCI/X Error */ -#define TSI148_LCSR_INTEN_VERREN (1<<12) /* VMEbus Error */ -#define TSI148_LCSR_INTEN_VIEEN (1<<11) /* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTEN_IACKEN (1<<10) /* IACK */ -#define TSI148_LCSR_INTEN_SYSFLEN (1<<9) /* System Fail */ -#define TSI148_LCSR_INTEN_ACFLEN (1<<8) /* AC Fail */ -#define TSI148_LCSR_INTEN_IRQ7EN (1<<7) /* IRQ7 */ -#define TSI148_LCSR_INTEN_IRQ6EN (1<<6) /* IRQ6 */ -#define TSI148_LCSR_INTEN_IRQ5EN (1<<5) /* IRQ5 */ -#define TSI148_LCSR_INTEN_IRQ4EN (1<<4) /* IRQ4 */ -#define TSI148_LCSR_INTEN_IRQ3EN (1<<3) /* IRQ3 */ -#define TSI148_LCSR_INTEN_IRQ2EN (1<<2) /* IRQ2 */ -#define TSI148_LCSR_INTEN_IRQ1EN (1<<1) /* IRQ1 */ - -static const int TSI148_LCSR_INTEN_LMEN[4] = { TSI148_LCSR_INTEN_LM0EN, - TSI148_LCSR_INTEN_LM1EN, - TSI148_LCSR_INTEN_LM2EN, - TSI148_LCSR_INTEN_LM3EN }; - -static const int TSI148_LCSR_INTEN_IRQEN[7] = { TSI148_LCSR_INTEN_IRQ1EN, - TSI148_LCSR_INTEN_IRQ2EN, - TSI148_LCSR_INTEN_IRQ3EN, - TSI148_LCSR_INTEN_IRQ4EN, - TSI148_LCSR_INTEN_IRQ5EN, - TSI148_LCSR_INTEN_IRQ6EN, - TSI148_LCSR_INTEN_IRQ7EN }; - -/* - * Interrupt Enable Out Register CRG + $444 - */ -#define TSI148_LCSR_INTEO_DMA1EO (1<<25) /* DMAC 1 */ -#define TSI148_LCSR_INTEO_DMA0EO (1<<24) /* DMAC 0 */ -#define TSI148_LCSR_INTEO_LM3EO (1<<23) /* Loc Monitor 3 */ -#define TSI148_LCSR_INTEO_LM2EO (1<<22) /* Loc Monitor 2 */ -#define TSI148_LCSR_INTEO_LM1EO (1<<21) /* Loc Monitor 1 */ -#define TSI148_LCSR_INTEO_LM0EO (1<<20) /* Location Monitor 0 */ -#define TSI148_LCSR_INTEO_MB3EO (1<<19) /* Mail Box 3 */ -#define TSI148_LCSR_INTEO_MB2EO (1<<18) /* Mail Box 2 */ -#define TSI148_LCSR_INTEO_MB1EO (1<<17) /* Mail Box 1 */ -#define TSI148_LCSR_INTEO_MB0EO (1<<16) /* Mail Box 0 */ -#define TSI148_LCSR_INTEO_PERREO (1<<13) /* PCI/X Error */ -#define TSI148_LCSR_INTEO_VERREO (1<<12) /* VMEbus Error */ -#define TSI148_LCSR_INTEO_VIEEO (1<<11) /* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTEO_IACKEO (1<<10) /* IACK */ -#define TSI148_LCSR_INTEO_SYSFLEO (1<<9) /* System Fail */ -#define TSI148_LCSR_INTEO_ACFLEO (1<<8) /* AC Fail */ -#define TSI148_LCSR_INTEO_IRQ7EO (1<<7) /* IRQ7 */ -#define TSI148_LCSR_INTEO_IRQ6EO (1<<6) /* IRQ6 */ -#define TSI148_LCSR_INTEO_IRQ5EO (1<<5) /* IRQ5 */ -#define TSI148_LCSR_INTEO_IRQ4EO (1<<4) /* IRQ4 */ -#define TSI148_LCSR_INTEO_IRQ3EO (1<<3) /* IRQ3 */ -#define TSI148_LCSR_INTEO_IRQ2EO (1<<2) /* IRQ2 */ -#define TSI148_LCSR_INTEO_IRQ1EO (1<<1) /* IRQ1 */ - -static const int TSI148_LCSR_INTEO_LMEO[4] = { TSI148_LCSR_INTEO_LM0EO, - TSI148_LCSR_INTEO_LM1EO, - TSI148_LCSR_INTEO_LM2EO, - TSI148_LCSR_INTEO_LM3EO }; - -static const int TSI148_LCSR_INTEO_IRQEO[7] = { TSI148_LCSR_INTEO_IRQ1EO, - TSI148_LCSR_INTEO_IRQ2EO, - TSI148_LCSR_INTEO_IRQ3EO, - TSI148_LCSR_INTEO_IRQ4EO, - TSI148_LCSR_INTEO_IRQ5EO, - TSI148_LCSR_INTEO_IRQ6EO, - TSI148_LCSR_INTEO_IRQ7EO }; - -/* - * Interrupt Status Register CRG + $448 - */ -#define TSI148_LCSR_INTS_DMA1S (1<<25) /* DMA 1 */ -#define TSI148_LCSR_INTS_DMA0S (1<<24) /* DMA 0 */ -#define TSI148_LCSR_INTS_LM3S (1<<23) /* Location Monitor 3 */ -#define TSI148_LCSR_INTS_LM2S (1<<22) /* Location Monitor 2 */ -#define TSI148_LCSR_INTS_LM1S (1<<21) /* Location Monitor 1 */ -#define TSI148_LCSR_INTS_LM0S (1<<20) /* Location Monitor 0 */ -#define TSI148_LCSR_INTS_MB3S (1<<19) /* Mail Box 3 */ -#define TSI148_LCSR_INTS_MB2S (1<<18) /* Mail Box 2 */ -#define TSI148_LCSR_INTS_MB1S (1<<17) /* Mail Box 1 */ -#define TSI148_LCSR_INTS_MB0S (1<<16) /* Mail Box 0 */ -#define TSI148_LCSR_INTS_PERRS (1<<13) /* PCI/X Error */ -#define TSI148_LCSR_INTS_VERRS (1<<12) /* VMEbus Error */ -#define TSI148_LCSR_INTS_VIES (1<<11) /* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTS_IACKS (1<<10) /* IACK */ -#define TSI148_LCSR_INTS_SYSFLS (1<<9) /* System Fail */ -#define TSI148_LCSR_INTS_ACFLS (1<<8) /* AC Fail */ -#define TSI148_LCSR_INTS_IRQ7S (1<<7) /* IRQ7 */ -#define TSI148_LCSR_INTS_IRQ6S (1<<6) /* IRQ6 */ -#define TSI148_LCSR_INTS_IRQ5S (1<<5) /* IRQ5 */ -#define TSI148_LCSR_INTS_IRQ4S (1<<4) /* IRQ4 */ -#define TSI148_LCSR_INTS_IRQ3S (1<<3) /* IRQ3 */ -#define TSI148_LCSR_INTS_IRQ2S (1<<2) /* IRQ2 */ -#define TSI148_LCSR_INTS_IRQ1S (1<<1) /* IRQ1 */ - -static const int TSI148_LCSR_INTS_LMS[4] = { TSI148_LCSR_INTS_LM0S, - TSI148_LCSR_INTS_LM1S, - TSI148_LCSR_INTS_LM2S, - TSI148_LCSR_INTS_LM3S }; - -static const int TSI148_LCSR_INTS_MBS[4] = { TSI148_LCSR_INTS_MB0S, - TSI148_LCSR_INTS_MB1S, - TSI148_LCSR_INTS_MB2S, - TSI148_LCSR_INTS_MB3S }; - -/* - * Interrupt Clear Register CRG + $44C - */ -#define TSI148_LCSR_INTC_DMA1C (1<<25) /* DMA 1 */ -#define TSI148_LCSR_INTC_DMA0C (1<<24) /* DMA 0 */ -#define TSI148_LCSR_INTC_LM3C (1<<23) /* Location Monitor 3 */ -#define TSI148_LCSR_INTC_LM2C (1<<22) /* Location Monitor 2 */ -#define TSI148_LCSR_INTC_LM1C (1<<21) /* Location Monitor 1 */ -#define TSI148_LCSR_INTC_LM0C (1<<20) /* Location Monitor 0 */ -#define TSI148_LCSR_INTC_MB3C (1<<19) /* Mail Box 3 */ -#define TSI148_LCSR_INTC_MB2C (1<<18) /* Mail Box 2 */ -#define TSI148_LCSR_INTC_MB1C (1<<17) /* Mail Box 1 */ -#define TSI148_LCSR_INTC_MB0C (1<<16) /* Mail Box 0 */ -#define TSI148_LCSR_INTC_PERRC (1<<13) /* VMEbus Error */ -#define TSI148_LCSR_INTC_VERRC (1<<12) /* VMEbus Access Time-out */ -#define TSI148_LCSR_INTC_VIEC (1<<11) /* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTC_IACKC (1<<10) /* IACK */ -#define TSI148_LCSR_INTC_SYSFLC (1<<9) /* System Fail */ -#define TSI148_LCSR_INTC_ACFLC (1<<8) /* AC Fail */ - -static const int TSI148_LCSR_INTC_LMC[4] = { TSI148_LCSR_INTC_LM0C, - TSI148_LCSR_INTC_LM1C, - TSI148_LCSR_INTC_LM2C, - TSI148_LCSR_INTC_LM3C }; - -static const int TSI148_LCSR_INTC_MBC[4] = { TSI148_LCSR_INTC_MB0C, - TSI148_LCSR_INTC_MB1C, - TSI148_LCSR_INTC_MB2C, - TSI148_LCSR_INTC_MB3C }; - -/* - * Interrupt Map Register 1 CRG + $458 - */ -#define TSI148_LCSR_INTM1_DMA1M_M (3<<18) /* DMA 1 */ -#define TSI148_LCSR_INTM1_DMA0M_M (3<<16) /* DMA 0 */ -#define TSI148_LCSR_INTM1_LM3M_M (3<<14) /* Location Monitor 3 */ -#define TSI148_LCSR_INTM1_LM2M_M (3<<12) /* Location Monitor 2 */ -#define TSI148_LCSR_INTM1_LM1M_M (3<<10) /* Location Monitor 1 */ -#define TSI148_LCSR_INTM1_LM0M_M (3<<8) /* Location Monitor 0 */ -#define TSI148_LCSR_INTM1_MB3M_M (3<<6) /* Mail Box 3 */ -#define TSI148_LCSR_INTM1_MB2M_M (3<<4) /* Mail Box 2 */ -#define TSI148_LCSR_INTM1_MB1M_M (3<<2) /* Mail Box 1 */ -#define TSI148_LCSR_INTM1_MB0M_M (3<<0) /* Mail Box 0 */ - -/* - * Interrupt Map Register 2 CRG + $45C - */ -#define TSI148_LCSR_INTM2_PERRM_M (3<<26) /* PCI Bus Error */ -#define TSI148_LCSR_INTM2_VERRM_M (3<<24) /* VMEbus Error */ -#define TSI148_LCSR_INTM2_VIEM_M (3<<22) /* VMEbus IRQ Edge */ -#define TSI148_LCSR_INTM2_IACKM_M (3<<20) /* IACK */ -#define TSI148_LCSR_INTM2_SYSFLM_M (3<<18) /* System Fail */ -#define TSI148_LCSR_INTM2_ACFLM_M (3<<16) /* AC Fail */ -#define TSI148_LCSR_INTM2_IRQ7M_M (3<<14) /* IRQ7 */ -#define TSI148_LCSR_INTM2_IRQ6M_M (3<<12) /* IRQ6 */ -#define TSI148_LCSR_INTM2_IRQ5M_M (3<<10) /* IRQ5 */ -#define TSI148_LCSR_INTM2_IRQ4M_M (3<<8) /* IRQ4 */ -#define TSI148_LCSR_INTM2_IRQ3M_M (3<<6) /* IRQ3 */ -#define TSI148_LCSR_INTM2_IRQ2M_M (3<<4) /* IRQ2 */ -#define TSI148_LCSR_INTM2_IRQ1M_M (3<<2) /* IRQ1 */ - -/* - * DMA Control (0-1) Registers CRG + $500 - */ -#define TSI148_LCSR_DCTL_ABT (1<<27) /* Abort */ -#define TSI148_LCSR_DCTL_PAU (1<<26) /* Pause */ -#define TSI148_LCSR_DCTL_DGO (1<<25) /* DMA Go */ - -#define TSI148_LCSR_DCTL_MOD (1<<23) /* Mode */ - -#define TSI148_LCSR_DCTL_VBKS_M (7<<12) /* VMEbus block Size MASK */ -#define TSI148_LCSR_DCTL_VBKS_32 (0<<12) /* VMEbus block Size 32 */ -#define TSI148_LCSR_DCTL_VBKS_64 (1<<12) /* VMEbus block Size 64 */ -#define TSI148_LCSR_DCTL_VBKS_128 (2<<12) /* VMEbus block Size 128 */ -#define TSI148_LCSR_DCTL_VBKS_256 (3<<12) /* VMEbus block Size 256 */ -#define TSI148_LCSR_DCTL_VBKS_512 (4<<12) /* VMEbus block Size 512 */ -#define TSI148_LCSR_DCTL_VBKS_1024 (5<<12) /* VMEbus block Size 1024 */ -#define TSI148_LCSR_DCTL_VBKS_2048 (6<<12) /* VMEbus block Size 2048 */ -#define TSI148_LCSR_DCTL_VBKS_4096 (7<<12) /* VMEbus block Size 4096 */ - -#define TSI148_LCSR_DCTL_VBOT_M (7<<8) /* VMEbus back-off MASK */ -#define TSI148_LCSR_DCTL_VBOT_0 (0<<8) /* VMEbus back-off 0us */ -#define TSI148_LCSR_DCTL_VBOT_1 (1<<8) /* VMEbus back-off 1us */ -#define TSI148_LCSR_DCTL_VBOT_2 (2<<8) /* VMEbus back-off 2us */ -#define TSI148_LCSR_DCTL_VBOT_4 (3<<8) /* VMEbus back-off 4us */ -#define TSI148_LCSR_DCTL_VBOT_8 (4<<8) /* VMEbus back-off 8us */ -#define TSI148_LCSR_DCTL_VBOT_16 (5<<8) /* VMEbus back-off 16us */ -#define TSI148_LCSR_DCTL_VBOT_32 (6<<8) /* VMEbus back-off 32us */ -#define TSI148_LCSR_DCTL_VBOT_64 (7<<8) /* VMEbus back-off 64us */ - -#define TSI148_LCSR_DCTL_PBKS_M (7<<4) /* PCI block size MASK */ -#define TSI148_LCSR_DCTL_PBKS_32 (0<<4) /* PCI block size 32 bytes */ -#define TSI148_LCSR_DCTL_PBKS_64 (1<<4) /* PCI block size 64 bytes */ -#define TSI148_LCSR_DCTL_PBKS_128 (2<<4) /* PCI block size 128 bytes */ -#define TSI148_LCSR_DCTL_PBKS_256 (3<<4) /* PCI block size 256 bytes */ -#define TSI148_LCSR_DCTL_PBKS_512 (4<<4) /* PCI block size 512 bytes */ -#define TSI148_LCSR_DCTL_PBKS_1024 (5<<4) /* PCI block size 1024 bytes */ -#define TSI148_LCSR_DCTL_PBKS_2048 (6<<4) /* PCI block size 2048 bytes */ -#define TSI148_LCSR_DCTL_PBKS_4096 (7<<4) /* PCI block size 4096 bytes */ - -#define TSI148_LCSR_DCTL_PBOT_M (7<<0) /* PCI back off MASK */ -#define TSI148_LCSR_DCTL_PBOT_0 (0<<0) /* PCI back off 0us */ -#define TSI148_LCSR_DCTL_PBOT_1 (1<<0) /* PCI back off 1us */ -#define TSI148_LCSR_DCTL_PBOT_2 (2<<0) /* PCI back off 2us */ -#define TSI148_LCSR_DCTL_PBOT_4 (3<<0) /* PCI back off 3us */ -#define TSI148_LCSR_DCTL_PBOT_8 (4<<0) /* PCI back off 4us */ -#define TSI148_LCSR_DCTL_PBOT_16 (5<<0) /* PCI back off 8us */ -#define TSI148_LCSR_DCTL_PBOT_32 (6<<0) /* PCI back off 16us */ -#define TSI148_LCSR_DCTL_PBOT_64 (7<<0) /* PCI back off 32us */ - -/* - * DMA Status Registers (0-1) CRG + $504 - */ -#define TSI148_LCSR_DSTA_SMA (1<<31) /* PCI Signalled Master Abt */ -#define TSI148_LCSR_DSTA_RTA (1<<30) /* PCI Received Target Abt */ -#define TSI148_LCSR_DSTA_MRC (1<<29) /* PCI Max Retry Count */ -#define TSI148_LCSR_DSTA_VBE (1<<28) /* VMEbus error */ -#define TSI148_LCSR_DSTA_ABT (1<<27) /* Abort */ -#define TSI148_LCSR_DSTA_PAU (1<<26) /* Pause */ -#define TSI148_LCSR_DSTA_DON (1<<25) /* Done */ -#define TSI148_LCSR_DSTA_BSY (1<<24) /* Busy */ - -/* - * DMA Current Link Address Lower (0-1) - */ -#define TSI148_LCSR_DCLAL_M (0x3FFFFFF<<6) /* Mask */ - -/* - * DMA Source Attribute (0-1) Reg - */ -#define TSI148_LCSR_DSAT_TYP_M (3<<28) /* Source Bus Type */ -#define TSI148_LCSR_DSAT_TYP_PCI (0<<28) /* PCI Bus */ -#define TSI148_LCSR_DSAT_TYP_VME (1<<28) /* VMEbus */ -#define TSI148_LCSR_DSAT_TYP_PAT (2<<28) /* Data Pattern */ - -#define TSI148_LCSR_DSAT_PSZ (1<<25) /* Pattern Size */ -#define TSI148_LCSR_DSAT_NIN (1<<24) /* No Increment */ - -#define TSI148_LCSR_DSAT_2eSSTM_M (3<<11) /* 2eSST Trans Rate Mask */ -#define TSI148_LCSR_DSAT_2eSSTM_160 (0<<11) /* 160 MB/s */ -#define TSI148_LCSR_DSAT_2eSSTM_267 (1<<11) /* 267 MB/s */ -#define TSI148_LCSR_DSAT_2eSSTM_320 (2<<11) /* 320 MB/s */ - -#define TSI148_LCSR_DSAT_TM_M (7<<8) /* Bus Transfer Protocol Mask */ -#define TSI148_LCSR_DSAT_TM_SCT (0<<8) /* SCT */ -#define TSI148_LCSR_DSAT_TM_BLT (1<<8) /* BLT */ -#define TSI148_LCSR_DSAT_TM_MBLT (2<<8) /* MBLT */ -#define TSI148_LCSR_DSAT_TM_2eVME (3<<8) /* 2eVME */ -#define TSI148_LCSR_DSAT_TM_2eSST (4<<8) /* 2eSST */ -#define TSI148_LCSR_DSAT_TM_2eSSTB (5<<8) /* 2eSST Broadcast */ - -#define TSI148_LCSR_DSAT_DBW_M (3<<6) /* Max Data Width MASK */ -#define TSI148_LCSR_DSAT_DBW_16 (0<<6) /* 16 Bits */ -#define TSI148_LCSR_DSAT_DBW_32 (1<<6) /* 32 Bits */ - -#define TSI148_LCSR_DSAT_SUP (1<<5) /* Supervisory Mode */ -#define TSI148_LCSR_DSAT_PGM (1<<4) /* Program Mode */ - -#define TSI148_LCSR_DSAT_AMODE_M (0xf<<0) /* Address Space Mask */ -#define TSI148_LCSR_DSAT_AMODE_A16 (0<<0) /* A16 */ -#define TSI148_LCSR_DSAT_AMODE_A24 (1<<0) /* A24 */ -#define TSI148_LCSR_DSAT_AMODE_A32 (2<<0) /* A32 */ -#define TSI148_LCSR_DSAT_AMODE_A64 (4<<0) /* A64 */ -#define TSI148_LCSR_DSAT_AMODE_CRCSR (5<<0) /* CR/CSR */ -#define TSI148_LCSR_DSAT_AMODE_USER1 (8<<0) /* User1 */ -#define TSI148_LCSR_DSAT_AMODE_USER2 (9<<0) /* User2 */ -#define TSI148_LCSR_DSAT_AMODE_USER3 (0xa<<0) /* User3 */ -#define TSI148_LCSR_DSAT_AMODE_USER4 (0xb<<0) /* User4 */ - -/* - * DMA Destination Attribute Registers (0-1) - */ -#define TSI148_LCSR_DDAT_TYP_PCI (0<<28) /* Destination PCI Bus */ -#define TSI148_LCSR_DDAT_TYP_VME (1<<28) /* Destination VMEbus */ - -#define TSI148_LCSR_DDAT_2eSSTM_M (3<<11) /* 2eSST Transfer Rate Mask */ -#define TSI148_LCSR_DDAT_2eSSTM_160 (0<<11) /* 160 MB/s */ -#define TSI148_LCSR_DDAT_2eSSTM_267 (1<<11) /* 267 MB/s */ -#define TSI148_LCSR_DDAT_2eSSTM_320 (2<<11) /* 320 MB/s */ - -#define TSI148_LCSR_DDAT_TM_M (7<<8) /* Bus Transfer Protocol Mask */ -#define TSI148_LCSR_DDAT_TM_SCT (0<<8) /* SCT */ -#define TSI148_LCSR_DDAT_TM_BLT (1<<8) /* BLT */ -#define TSI148_LCSR_DDAT_TM_MBLT (2<<8) /* MBLT */ -#define TSI148_LCSR_DDAT_TM_2eVME (3<<8) /* 2eVME */ -#define TSI148_LCSR_DDAT_TM_2eSST (4<<8) /* 2eSST */ -#define TSI148_LCSR_DDAT_TM_2eSSTB (5<<8) /* 2eSST Broadcast */ - -#define TSI148_LCSR_DDAT_DBW_M (3<<6) /* Max Data Width MASK */ -#define TSI148_LCSR_DDAT_DBW_16 (0<<6) /* 16 Bits */ -#define TSI148_LCSR_DDAT_DBW_32 (1<<6) /* 32 Bits */ - -#define TSI148_LCSR_DDAT_SUP (1<<5) /* Supervisory/User Access */ -#define TSI148_LCSR_DDAT_PGM (1<<4) /* Program/Data Access */ - -#define TSI148_LCSR_DDAT_AMODE_M (0xf<<0) /* Address Space Mask */ -#define TSI148_LCSR_DDAT_AMODE_A16 (0<<0) /* A16 */ -#define TSI148_LCSR_DDAT_AMODE_A24 (1<<0) /* A24 */ -#define TSI148_LCSR_DDAT_AMODE_A32 (2<<0) /* A32 */ -#define TSI148_LCSR_DDAT_AMODE_A64 (4<<0) /* A64 */ -#define TSI148_LCSR_DDAT_AMODE_CRCSR (5<<0) /* CRC/SR */ -#define TSI148_LCSR_DDAT_AMODE_USER1 (8<<0) /* User1 */ -#define TSI148_LCSR_DDAT_AMODE_USER2 (9<<0) /* User2 */ -#define TSI148_LCSR_DDAT_AMODE_USER3 (0xa<<0) /* User3 */ -#define TSI148_LCSR_DDAT_AMODE_USER4 (0xb<<0) /* User4 */ - -/* - * DMA Next Link Address Lower - */ -#define TSI148_LCSR_DNLAL_DNLAL_M (0x3FFFFFF<<6) /* Address Mask */ -#define TSI148_LCSR_DNLAL_LLA (1<<0) /* Last Link Address Indicator */ - -/* - * DMA 2eSST Broadcast Select - */ -#define TSI148_LCSR_DBS_M (0x1FFFFF<<0) /* Mask */ - -/* - * GCSR Register Group - */ - -/* - * GCSR Control and Status Register CRG + $604 - */ -#define TSI148_GCSR_GCTRL_LRST (1<<15) /* Local Reset */ -#define TSI148_GCSR_GCTRL_SFAILEN (1<<14) /* System Fail enable */ -#define TSI148_GCSR_GCTRL_BDFAILS (1<<13) /* Board Fail Status */ -#define TSI148_GCSR_GCTRL_SCON (1<<12) /* System Copntroller */ -#define TSI148_GCSR_GCTRL_MEN (1<<11) /* Module Enable (READY) */ - -#define TSI148_GCSR_GCTRL_LMI3S (1<<7) /* Loc Monitor 3 Int Status */ -#define TSI148_GCSR_GCTRL_LMI2S (1<<6) /* Loc Monitor 2 Int Status */ -#define TSI148_GCSR_GCTRL_LMI1S (1<<5) /* Loc Monitor 1 Int Status */ -#define TSI148_GCSR_GCTRL_LMI0S (1<<4) /* Loc Monitor 0 Int Status */ -#define TSI148_GCSR_GCTRL_MBI3S (1<<3) /* Mail box 3 Int Status */ -#define TSI148_GCSR_GCTRL_MBI2S (1<<2) /* Mail box 2 Int Status */ -#define TSI148_GCSR_GCTRL_MBI1S (1<<1) /* Mail box 1 Int Status */ -#define TSI148_GCSR_GCTRL_MBI0S (1<<0) /* Mail box 0 Int Status */ - -#define TSI148_GCSR_GAP (1<<5) /* Geographic Addr Parity */ -#define TSI148_GCSR_GA_M (0x1F<<0) /* Geographic Address Mask */ - -/* - * CR/CSR Register Group - */ - -/* - * CR/CSR Bit Clear Register CRG + $FF4 - */ -#define TSI148_CRCSR_CSRBCR_LRSTC (1<<7) /* Local Reset Clear */ -#define TSI148_CRCSR_CSRBCR_SFAILC (1<<6) /* System Fail Enable Clear */ -#define TSI148_CRCSR_CSRBCR_BDFAILS (1<<5) /* Board Fail Status */ -#define TSI148_CRCSR_CSRBCR_MENC (1<<4) /* Module Enable Clear */ -#define TSI148_CRCSR_CSRBCR_BERRSC (1<<3) /* Bus Error Status Clear */ - -/* - * CR/CSR Bit Set Register CRG+$FF8 - */ -#define TSI148_CRCSR_CSRBSR_LISTS (1<<7) /* Local Reset Clear */ -#define TSI148_CRCSR_CSRBSR_SFAILS (1<<6) /* System Fail Enable Clear */ -#define TSI148_CRCSR_CSRBSR_BDFAILS (1<<5) /* Board Fail Status */ -#define TSI148_CRCSR_CSRBSR_MENS (1<<4) /* Module Enable Clear */ -#define TSI148_CRCSR_CSRBSR_BERRS (1<<3) /* Bus Error Status Clear */ - -/* - * CR/CSR Base Address Register CRG + FFC - */ -#define TSI148_CRCSR_CBAR_M (0x1F<<3) /* Mask */ - -#endif /* TSI148_H */ diff --git a/drivers/staging/vme/devices/Kconfig b/drivers/staging/vme/devices/Kconfig index 55ec30cb1fa2..d0cab1766190 100644 --- a/drivers/staging/vme/devices/Kconfig +++ b/drivers/staging/vme/devices/Kconfig @@ -2,6 +2,7 @@ comment "VME Device Drivers" config VME_USER tristate "VME user space access driver" + depends on STAGING help If you say Y here you want to be able to access a limited number of VME windows in a manner at least semi-compatible with the interface @@ -9,7 +10,7 @@ config VME_USER config VME_PIO2 tristate "GE PIO2 VME" - depends on GPIOLIB + depends on STAGING && GPIOLIB help Say Y here to include support for the GE PIO2. The PIO2 is a 6U VME slave card, implementing 32 solid-state relay switched IO lines, in diff --git a/drivers/staging/vme/devices/vme_pio2_cntr.c b/drivers/staging/vme/devices/vme_pio2_cntr.c index 08e0d59806ca..6335471faa36 100644 --- a/drivers/staging/vme/devices/vme_pio2_cntr.c +++ b/drivers/staging/vme/devices/vme_pio2_cntr.c @@ -17,8 +17,8 @@ #include #include #include +#include -#include "../vme.h" #include "vme_pio2.h" static int pio2_cntr_irq_set(struct pio2_card *card, int id) diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c index d476b2e9d39f..78228d447f25 100644 --- a/drivers/staging/vme/devices/vme_pio2_core.c +++ b/drivers/staging/vme/devices/vme_pio2_core.c @@ -19,8 +19,8 @@ #include #include #include +#include -#include "../vme.h" #include "vme_pio2.h" diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c index 9c459c1b6eb8..ad76a477825b 100644 --- a/drivers/staging/vme/devices/vme_pio2_gpio.c +++ b/drivers/staging/vme/devices/vme_pio2_gpio.c @@ -20,8 +20,8 @@ #include #include #include +#include -#include "../vme.h" #include "vme_pio2.h" static const char driver_name[] = "pio2_gpio"; diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index 10269d59942f..e24a6f95db12 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -36,8 +36,8 @@ #include #include +#include -#include "../vme.h" #include "vme_user.h" static DEFINE_MUTEX(vme_user_mutex); diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c deleted file mode 100644 index fd51c2d44718..000000000000 --- a/drivers/staging/vme/vme.c +++ /dev/null @@ -1,1517 +0,0 @@ -/* - * VME Bridge Framework - * - * Author: Martyn Welch - * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. - * - * Based on work by Tom Armistead and Ajit Prem - * Copyright 2004 Motorola Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "vme.h" -#include "vme_bridge.h" - -/* Bitmask and list of registered buses both protected by common mutex */ -static unsigned int vme_bus_numbers; -static LIST_HEAD(vme_bus_list); -static DEFINE_MUTEX(vme_buses_lock); - -static void __exit vme_exit(void); -static int __init vme_init(void); - -static struct vme_dev *dev_to_vme_dev(struct device *dev) -{ - return container_of(dev, struct vme_dev, dev); -} - -/* - * Find the bridge that the resource is associated with. - */ -static struct vme_bridge *find_bridge(struct vme_resource *resource) -{ - /* Get list to search */ - switch (resource->type) { - case VME_MASTER: - return list_entry(resource->entry, struct vme_master_resource, - list)->parent; - break; - case VME_SLAVE: - return list_entry(resource->entry, struct vme_slave_resource, - list)->parent; - break; - case VME_DMA: - return list_entry(resource->entry, struct vme_dma_resource, - list)->parent; - break; - case VME_LM: - return list_entry(resource->entry, struct vme_lm_resource, - list)->parent; - break; - default: - printk(KERN_ERR "Unknown resource type\n"); - return NULL; - break; - } -} - -/* - * Allocate a contiguous block of memory for use by the driver. This is used to - * create the buffers for the slave windows. - */ -void *vme_alloc_consistent(struct vme_resource *resource, size_t size, - dma_addr_t *dma) -{ - struct vme_bridge *bridge; - - if (resource == NULL) { - printk(KERN_ERR "No resource\n"); - return NULL; - } - - bridge = find_bridge(resource); - if (bridge == NULL) { - printk(KERN_ERR "Can't find bridge\n"); - return NULL; - } - - if (bridge->parent == NULL) { - printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name); - return NULL; - } - - if (bridge->alloc_consistent == NULL) { - printk(KERN_ERR "alloc_consistent not supported by bridge %s\n", - bridge->name); - return NULL; - } - - return bridge->alloc_consistent(bridge->parent, size, dma); -} -EXPORT_SYMBOL(vme_alloc_consistent); - -/* - * Free previously allocated contiguous block of memory. - */ -void vme_free_consistent(struct vme_resource *resource, size_t size, - void *vaddr, dma_addr_t dma) -{ - struct vme_bridge *bridge; - - if (resource == NULL) { - printk(KERN_ERR "No resource\n"); - return; - } - - bridge = find_bridge(resource); - if (bridge == NULL) { - printk(KERN_ERR "Can't find bridge\n"); - return; - } - - if (bridge->parent == NULL) { - printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name); - return; - } - - if (bridge->free_consistent == NULL) { - printk(KERN_ERR "free_consistent not supported by bridge %s\n", - bridge->name); - return; - } - - bridge->free_consistent(bridge->parent, size, vaddr, dma); -} -EXPORT_SYMBOL(vme_free_consistent); - -size_t vme_get_size(struct vme_resource *resource) -{ - int enabled, retval; - unsigned long long base, size; - dma_addr_t buf_base; - u32 aspace, cycle, dwidth; - - switch (resource->type) { - case VME_MASTER: - retval = vme_master_get(resource, &enabled, &base, &size, - &aspace, &cycle, &dwidth); - - return size; - break; - case VME_SLAVE: - retval = vme_slave_get(resource, &enabled, &base, &size, - &buf_base, &aspace, &cycle); - - return size; - break; - case VME_DMA: - return 0; - break; - default: - printk(KERN_ERR "Unknown resource type\n"); - return 0; - break; - } -} -EXPORT_SYMBOL(vme_get_size); - -static int vme_check_window(u32 aspace, unsigned long long vme_base, - unsigned long long size) -{ - int retval = 0; - - switch (aspace) { - case VME_A16: - if (((vme_base + size) > VME_A16_MAX) || - (vme_base > VME_A16_MAX)) - retval = -EFAULT; - break; - case VME_A24: - if (((vme_base + size) > VME_A24_MAX) || - (vme_base > VME_A24_MAX)) - retval = -EFAULT; - break; - case VME_A32: - if (((vme_base + size) > VME_A32_MAX) || - (vme_base > VME_A32_MAX)) - retval = -EFAULT; - break; - case VME_A64: - /* - * Any value held in an unsigned long long can be used as the - * base - */ - break; - case VME_CRCSR: - if (((vme_base + size) > VME_CRCSR_MAX) || - (vme_base > VME_CRCSR_MAX)) - retval = -EFAULT; - break; - case VME_USER1: - case VME_USER2: - case VME_USER3: - case VME_USER4: - /* User Defined */ - break; - default: - printk(KERN_ERR "Invalid address space\n"); - retval = -EINVAL; - break; - } - - return retval; -} - -/* - * Request a slave image with specific attributes, return some unique - * identifier. - */ -struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address, - u32 cycle) -{ - struct vme_bridge *bridge; - struct list_head *slave_pos = NULL; - struct vme_slave_resource *allocated_image = NULL; - struct vme_slave_resource *slave_image = NULL; - struct vme_resource *resource = NULL; - - bridge = vdev->bridge; - if (bridge == NULL) { - printk(KERN_ERR "Can't find VME bus\n"); - goto err_bus; - } - - /* Loop through slave resources */ - list_for_each(slave_pos, &bridge->slave_resources) { - slave_image = list_entry(slave_pos, - struct vme_slave_resource, list); - - if (slave_image == NULL) { - printk(KERN_ERR "Registered NULL Slave resource\n"); - continue; - } - - /* Find an unlocked and compatible image */ - mutex_lock(&slave_image->mtx); - if (((slave_image->address_attr & address) == address) && - ((slave_image->cycle_attr & cycle) == cycle) && - (slave_image->locked == 0)) { - - slave_image->locked = 1; - mutex_unlock(&slave_image->mtx); - allocated_image = slave_image; - break; - } - mutex_unlock(&slave_image->mtx); - } - - /* No free image */ - if (allocated_image == NULL) - goto err_image; - - resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); - if (resource == NULL) { - printk(KERN_WARNING "Unable to allocate resource structure\n"); - goto err_alloc; - } - resource->type = VME_SLAVE; - resource->entry = &allocated_image->list; - - return resource; - -err_alloc: - /* Unlock image */ - mutex_lock(&slave_image->mtx); - slave_image->locked = 0; - mutex_unlock(&slave_image->mtx); -err_image: -err_bus: - return NULL; -} -EXPORT_SYMBOL(vme_slave_request); - -int vme_slave_set(struct vme_resource *resource, int enabled, - unsigned long long vme_base, unsigned long long size, - dma_addr_t buf_base, u32 aspace, u32 cycle) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_slave_resource *image; - int retval; - - if (resource->type != VME_SLAVE) { - printk(KERN_ERR "Not a slave resource\n"); - return -EINVAL; - } - - image = list_entry(resource->entry, struct vme_slave_resource, list); - - if (bridge->slave_set == NULL) { - printk(KERN_ERR "Function not supported\n"); - return -ENOSYS; - } - - if (!(((image->address_attr & aspace) == aspace) && - ((image->cycle_attr & cycle) == cycle))) { - printk(KERN_ERR "Invalid attributes\n"); - return -EINVAL; - } - - retval = vme_check_window(aspace, vme_base, size); - if (retval) - return retval; - - return bridge->slave_set(image, enabled, vme_base, size, buf_base, - aspace, cycle); -} -EXPORT_SYMBOL(vme_slave_set); - -int vme_slave_get(struct vme_resource *resource, int *enabled, - unsigned long long *vme_base, unsigned long long *size, - dma_addr_t *buf_base, u32 *aspace, u32 *cycle) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_slave_resource *image; - - if (resource->type != VME_SLAVE) { - printk(KERN_ERR "Not a slave resource\n"); - return -EINVAL; - } - - image = list_entry(resource->entry, struct vme_slave_resource, list); - - if (bridge->slave_get == NULL) { - printk(KERN_ERR "vme_slave_get not supported\n"); - return -EINVAL; - } - - return bridge->slave_get(image, enabled, vme_base, size, buf_base, - aspace, cycle); -} -EXPORT_SYMBOL(vme_slave_get); - -void vme_slave_free(struct vme_resource *resource) -{ - struct vme_slave_resource *slave_image; - - if (resource->type != VME_SLAVE) { - printk(KERN_ERR "Not a slave resource\n"); - return; - } - - slave_image = list_entry(resource->entry, struct vme_slave_resource, - list); - if (slave_image == NULL) { - printk(KERN_ERR "Can't find slave resource\n"); - return; - } - - /* Unlock image */ - mutex_lock(&slave_image->mtx); - if (slave_image->locked == 0) - printk(KERN_ERR "Image is already free\n"); - - slave_image->locked = 0; - mutex_unlock(&slave_image->mtx); - - /* Free up resource memory */ - kfree(resource); -} -EXPORT_SYMBOL(vme_slave_free); - -/* - * Request a master image with specific attributes, return some unique - * identifier. - */ -struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address, - u32 cycle, u32 dwidth) -{ - struct vme_bridge *bridge; - struct list_head *master_pos = NULL; - struct vme_master_resource *allocated_image = NULL; - struct vme_master_resource *master_image = NULL; - struct vme_resource *resource = NULL; - - bridge = vdev->bridge; - if (bridge == NULL) { - printk(KERN_ERR "Can't find VME bus\n"); - goto err_bus; - } - - /* Loop through master resources */ - list_for_each(master_pos, &bridge->master_resources) { - master_image = list_entry(master_pos, - struct vme_master_resource, list); - - if (master_image == NULL) { - printk(KERN_WARNING "Registered NULL master resource\n"); - continue; - } - - /* Find an unlocked and compatible image */ - spin_lock(&master_image->lock); - if (((master_image->address_attr & address) == address) && - ((master_image->cycle_attr & cycle) == cycle) && - ((master_image->width_attr & dwidth) == dwidth) && - (master_image->locked == 0)) { - - master_image->locked = 1; - spin_unlock(&master_image->lock); - allocated_image = master_image; - break; - } - spin_unlock(&master_image->lock); - } - - /* Check to see if we found a resource */ - if (allocated_image == NULL) { - printk(KERN_ERR "Can't find a suitable resource\n"); - goto err_image; - } - - resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); - if (resource == NULL) { - printk(KERN_ERR "Unable to allocate resource structure\n"); - goto err_alloc; - } - resource->type = VME_MASTER; - resource->entry = &allocated_image->list; - - return resource; - -err_alloc: - /* Unlock image */ - spin_lock(&master_image->lock); - master_image->locked = 0; - spin_unlock(&master_image->lock); -err_image: -err_bus: - return NULL; -} -EXPORT_SYMBOL(vme_master_request); - -int vme_master_set(struct vme_resource *resource, int enabled, - unsigned long long vme_base, unsigned long long size, u32 aspace, - u32 cycle, u32 dwidth) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_master_resource *image; - int retval; - - if (resource->type != VME_MASTER) { - printk(KERN_ERR "Not a master resource\n"); - return -EINVAL; - } - - image = list_entry(resource->entry, struct vme_master_resource, list); - - if (bridge->master_set == NULL) { - printk(KERN_WARNING "vme_master_set not supported\n"); - return -EINVAL; - } - - if (!(((image->address_attr & aspace) == aspace) && - ((image->cycle_attr & cycle) == cycle) && - ((image->width_attr & dwidth) == dwidth))) { - printk(KERN_WARNING "Invalid attributes\n"); - return -EINVAL; - } - - retval = vme_check_window(aspace, vme_base, size); - if (retval) - return retval; - - return bridge->master_set(image, enabled, vme_base, size, aspace, - cycle, dwidth); -} -EXPORT_SYMBOL(vme_master_set); - -int vme_master_get(struct vme_resource *resource, int *enabled, - unsigned long long *vme_base, unsigned long long *size, u32 *aspace, - u32 *cycle, u32 *dwidth) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_master_resource *image; - - if (resource->type != VME_MASTER) { - printk(KERN_ERR "Not a master resource\n"); - return -EINVAL; - } - - image = list_entry(resource->entry, struct vme_master_resource, list); - - if (bridge->master_get == NULL) { - printk(KERN_WARNING "vme_master_set not supported\n"); - return -EINVAL; - } - - return bridge->master_get(image, enabled, vme_base, size, aspace, - cycle, dwidth); -} -EXPORT_SYMBOL(vme_master_get); - -/* - * Read data out of VME space into a buffer. - */ -ssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count, - loff_t offset) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_master_resource *image; - size_t length; - - if (bridge->master_read == NULL) { - printk(KERN_WARNING "Reading from resource not supported\n"); - return -EINVAL; - } - - if (resource->type != VME_MASTER) { - printk(KERN_ERR "Not a master resource\n"); - return -EINVAL; - } - - image = list_entry(resource->entry, struct vme_master_resource, list); - - length = vme_get_size(resource); - - if (offset > length) { - printk(KERN_WARNING "Invalid Offset\n"); - return -EFAULT; - } - - if ((offset + count) > length) - count = length - offset; - - return bridge->master_read(image, buf, count, offset); - -} -EXPORT_SYMBOL(vme_master_read); - -/* - * Write data out to VME space from a buffer. - */ -ssize_t vme_master_write(struct vme_resource *resource, void *buf, - size_t count, loff_t offset) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_master_resource *image; - size_t length; - - if (bridge->master_write == NULL) { - printk(KERN_WARNING "Writing to resource not supported\n"); - return -EINVAL; - } - - if (resource->type != VME_MASTER) { - printk(KERN_ERR "Not a master resource\n"); - return -EINVAL; - } - - image = list_entry(resource->entry, struct vme_master_resource, list); - - length = vme_get_size(resource); - - if (offset > length) { - printk(KERN_WARNING "Invalid Offset\n"); - return -EFAULT; - } - - if ((offset + count) > length) - count = length - offset; - - return bridge->master_write(image, buf, count, offset); -} -EXPORT_SYMBOL(vme_master_write); - -/* - * Perform RMW cycle to provided location. - */ -unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask, - unsigned int compare, unsigned int swap, loff_t offset) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_master_resource *image; - - if (bridge->master_rmw == NULL) { - printk(KERN_WARNING "Writing to resource not supported\n"); - return -EINVAL; - } - - if (resource->type != VME_MASTER) { - printk(KERN_ERR "Not a master resource\n"); - return -EINVAL; - } - - image = list_entry(resource->entry, struct vme_master_resource, list); - - return bridge->master_rmw(image, mask, compare, swap, offset); -} -EXPORT_SYMBOL(vme_master_rmw); - -void vme_master_free(struct vme_resource *resource) -{ - struct vme_master_resource *master_image; - - if (resource->type != VME_MASTER) { - printk(KERN_ERR "Not a master resource\n"); - return; - } - - master_image = list_entry(resource->entry, struct vme_master_resource, - list); - if (master_image == NULL) { - printk(KERN_ERR "Can't find master resource\n"); - return; - } - - /* Unlock image */ - spin_lock(&master_image->lock); - if (master_image->locked == 0) - printk(KERN_ERR "Image is already free\n"); - - master_image->locked = 0; - spin_unlock(&master_image->lock); - - /* Free up resource memory */ - kfree(resource); -} -EXPORT_SYMBOL(vme_master_free); - -/* - * Request a DMA controller with specific attributes, return some unique - * identifier. - */ -struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route) -{ - struct vme_bridge *bridge; - struct list_head *dma_pos = NULL; - struct vme_dma_resource *allocated_ctrlr = NULL; - struct vme_dma_resource *dma_ctrlr = NULL; - struct vme_resource *resource = NULL; - - /* XXX Not checking resource attributes */ - printk(KERN_ERR "No VME resource Attribute tests done\n"); - - bridge = vdev->bridge; - if (bridge == NULL) { - printk(KERN_ERR "Can't find VME bus\n"); - goto err_bus; - } - - /* Loop through DMA resources */ - list_for_each(dma_pos, &bridge->dma_resources) { - dma_ctrlr = list_entry(dma_pos, - struct vme_dma_resource, list); - - if (dma_ctrlr == NULL) { - printk(KERN_ERR "Registered NULL DMA resource\n"); - continue; - } - - /* Find an unlocked and compatible controller */ - mutex_lock(&dma_ctrlr->mtx); - if (((dma_ctrlr->route_attr & route) == route) && - (dma_ctrlr->locked == 0)) { - - dma_ctrlr->locked = 1; - mutex_unlock(&dma_ctrlr->mtx); - allocated_ctrlr = dma_ctrlr; - break; - } - mutex_unlock(&dma_ctrlr->mtx); - } - - /* Check to see if we found a resource */ - if (allocated_ctrlr == NULL) - goto err_ctrlr; - - resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); - if (resource == NULL) { - printk(KERN_WARNING "Unable to allocate resource structure\n"); - goto err_alloc; - } - resource->type = VME_DMA; - resource->entry = &allocated_ctrlr->list; - - return resource; - -err_alloc: - /* Unlock image */ - mutex_lock(&dma_ctrlr->mtx); - dma_ctrlr->locked = 0; - mutex_unlock(&dma_ctrlr->mtx); -err_ctrlr: -err_bus: - return NULL; -} -EXPORT_SYMBOL(vme_dma_request); - -/* - * Start new list - */ -struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource) -{ - struct vme_dma_resource *ctrlr; - struct vme_dma_list *dma_list; - - if (resource->type != VME_DMA) { - printk(KERN_ERR "Not a DMA resource\n"); - return NULL; - } - - ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); - - dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL); - if (dma_list == NULL) { - printk(KERN_ERR "Unable to allocate memory for new dma list\n"); - return NULL; - } - INIT_LIST_HEAD(&dma_list->entries); - dma_list->parent = ctrlr; - mutex_init(&dma_list->mtx); - - return dma_list; -} -EXPORT_SYMBOL(vme_new_dma_list); - -/* - * Create "Pattern" type attributes - */ -struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type) -{ - struct vme_dma_attr *attributes; - struct vme_dma_pattern *pattern_attr; - - attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); - if (attributes == NULL) { - printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); - goto err_attr; - } - - pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL); - if (pattern_attr == NULL) { - printk(KERN_ERR "Unable to allocate memory for pattern attributes\n"); - goto err_pat; - } - - attributes->type = VME_DMA_PATTERN; - attributes->private = (void *)pattern_attr; - - pattern_attr->pattern = pattern; - pattern_attr->type = type; - - return attributes; - -err_pat: - kfree(attributes); -err_attr: - return NULL; -} -EXPORT_SYMBOL(vme_dma_pattern_attribute); - -/* - * Create "PCI" type attributes - */ -struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address) -{ - struct vme_dma_attr *attributes; - struct vme_dma_pci *pci_attr; - - /* XXX Run some sanity checks here */ - - attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); - if (attributes == NULL) { - printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); - goto err_attr; - } - - pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL); - if (pci_attr == NULL) { - printk(KERN_ERR "Unable to allocate memory for pci attributes\n"); - goto err_pci; - } - - - - attributes->type = VME_DMA_PCI; - attributes->private = (void *)pci_attr; - - pci_attr->address = address; - - return attributes; - -err_pci: - kfree(attributes); -err_attr: - return NULL; -} -EXPORT_SYMBOL(vme_dma_pci_attribute); - -/* - * Create "VME" type attributes - */ -struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address, - u32 aspace, u32 cycle, u32 dwidth) -{ - struct vme_dma_attr *attributes; - struct vme_dma_vme *vme_attr; - - attributes = kmalloc( - sizeof(struct vme_dma_attr), GFP_KERNEL); - if (attributes == NULL) { - printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); - goto err_attr; - } - - vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL); - if (vme_attr == NULL) { - printk(KERN_ERR "Unable to allocate memory for vme attributes\n"); - goto err_vme; - } - - attributes->type = VME_DMA_VME; - attributes->private = (void *)vme_attr; - - vme_attr->address = address; - vme_attr->aspace = aspace; - vme_attr->cycle = cycle; - vme_attr->dwidth = dwidth; - - return attributes; - -err_vme: - kfree(attributes); -err_attr: - return NULL; -} -EXPORT_SYMBOL(vme_dma_vme_attribute); - -/* - * Free attribute - */ -void vme_dma_free_attribute(struct vme_dma_attr *attributes) -{ - kfree(attributes->private); - kfree(attributes); -} -EXPORT_SYMBOL(vme_dma_free_attribute); - -int vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, - struct vme_dma_attr *dest, size_t count) -{ - struct vme_bridge *bridge = list->parent->parent; - int retval; - - if (bridge->dma_list_add == NULL) { - printk(KERN_WARNING "Link List DMA generation not supported\n"); - return -EINVAL; - } - - if (!mutex_trylock(&list->mtx)) { - printk(KERN_ERR "Link List already submitted\n"); - return -EINVAL; - } - - retval = bridge->dma_list_add(list, src, dest, count); - - mutex_unlock(&list->mtx); - - return retval; -} -EXPORT_SYMBOL(vme_dma_list_add); - -int vme_dma_list_exec(struct vme_dma_list *list) -{ - struct vme_bridge *bridge = list->parent->parent; - int retval; - - if (bridge->dma_list_exec == NULL) { - printk(KERN_ERR "Link List DMA execution not supported\n"); - return -EINVAL; - } - - mutex_lock(&list->mtx); - - retval = bridge->dma_list_exec(list); - - mutex_unlock(&list->mtx); - - return retval; -} -EXPORT_SYMBOL(vme_dma_list_exec); - -int vme_dma_list_free(struct vme_dma_list *list) -{ - struct vme_bridge *bridge = list->parent->parent; - int retval; - - if (bridge->dma_list_empty == NULL) { - printk(KERN_WARNING "Emptying of Link Lists not supported\n"); - return -EINVAL; - } - - if (!mutex_trylock(&list->mtx)) { - printk(KERN_ERR "Link List in use\n"); - return -EINVAL; - } - - /* - * Empty out all of the entries from the dma list. We need to go to the - * low level driver as dma entries are driver specific. - */ - retval = bridge->dma_list_empty(list); - if (retval) { - printk(KERN_ERR "Unable to empty link-list entries\n"); - mutex_unlock(&list->mtx); - return retval; - } - mutex_unlock(&list->mtx); - kfree(list); - - return retval; -} -EXPORT_SYMBOL(vme_dma_list_free); - -int vme_dma_free(struct vme_resource *resource) -{ - struct vme_dma_resource *ctrlr; - - if (resource->type != VME_DMA) { - printk(KERN_ERR "Not a DMA resource\n"); - return -EINVAL; - } - - ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); - - if (!mutex_trylock(&ctrlr->mtx)) { - printk(KERN_ERR "Resource busy, can't free\n"); - return -EBUSY; - } - - if (!(list_empty(&ctrlr->pending) && list_empty(&ctrlr->running))) { - printk(KERN_WARNING "Resource still processing transfers\n"); - mutex_unlock(&ctrlr->mtx); - return -EBUSY; - } - - ctrlr->locked = 0; - - mutex_unlock(&ctrlr->mtx); - - return 0; -} -EXPORT_SYMBOL(vme_dma_free); - -void vme_irq_handler(struct vme_bridge *bridge, int level, int statid) -{ - void (*call)(int, int, void *); - void *priv_data; - - call = bridge->irq[level - 1].callback[statid].func; - priv_data = bridge->irq[level - 1].callback[statid].priv_data; - - if (call != NULL) - call(level, statid, priv_data); - else - printk(KERN_WARNING "Spurilous VME interrupt, level:%x, vector:%x\n", - level, statid); -} -EXPORT_SYMBOL(vme_irq_handler); - -int vme_irq_request(struct vme_dev *vdev, int level, int statid, - void (*callback)(int, int, void *), - void *priv_data) -{ - struct vme_bridge *bridge; - - bridge = vdev->bridge; - if (bridge == NULL) { - printk(KERN_ERR "Can't find VME bus\n"); - return -EINVAL; - } - - if ((level < 1) || (level > 7)) { - printk(KERN_ERR "Invalid interrupt level\n"); - return -EINVAL; - } - - if (bridge->irq_set == NULL) { - printk(KERN_ERR "Configuring interrupts not supported\n"); - return -EINVAL; - } - - mutex_lock(&bridge->irq_mtx); - - if (bridge->irq[level - 1].callback[statid].func) { - mutex_unlock(&bridge->irq_mtx); - printk(KERN_WARNING "VME Interrupt already taken\n"); - return -EBUSY; - } - - bridge->irq[level - 1].count++; - bridge->irq[level - 1].callback[statid].priv_data = priv_data; - bridge->irq[level - 1].callback[statid].func = callback; - - /* Enable IRQ level */ - bridge->irq_set(bridge, level, 1, 1); - - mutex_unlock(&bridge->irq_mtx); - - return 0; -} -EXPORT_SYMBOL(vme_irq_request); - -void vme_irq_free(struct vme_dev *vdev, int level, int statid) -{ - struct vme_bridge *bridge; - - bridge = vdev->bridge; - if (bridge == NULL) { - printk(KERN_ERR "Can't find VME bus\n"); - return; - } - - if ((level < 1) || (level > 7)) { - printk(KERN_ERR "Invalid interrupt level\n"); - return; - } - - if (bridge->irq_set == NULL) { - printk(KERN_ERR "Configuring interrupts not supported\n"); - return; - } - - mutex_lock(&bridge->irq_mtx); - - bridge->irq[level - 1].count--; - - /* Disable IRQ level if no more interrupts attached at this level*/ - if (bridge->irq[level - 1].count == 0) - bridge->irq_set(bridge, level, 0, 1); - - bridge->irq[level - 1].callback[statid].func = NULL; - bridge->irq[level - 1].callback[statid].priv_data = NULL; - - mutex_unlock(&bridge->irq_mtx); -} -EXPORT_SYMBOL(vme_irq_free); - -int vme_irq_generate(struct vme_dev *vdev, int level, int statid) -{ - struct vme_bridge *bridge; - - bridge = vdev->bridge; - if (bridge == NULL) { - printk(KERN_ERR "Can't find VME bus\n"); - return -EINVAL; - } - - if ((level < 1) || (level > 7)) { - printk(KERN_WARNING "Invalid interrupt level\n"); - return -EINVAL; - } - - if (bridge->irq_generate == NULL) { - printk(KERN_WARNING "Interrupt generation not supported\n"); - return -EINVAL; - } - - return bridge->irq_generate(bridge, level, statid); -} -EXPORT_SYMBOL(vme_irq_generate); - -/* - * Request the location monitor, return resource or NULL - */ -struct vme_resource *vme_lm_request(struct vme_dev *vdev) -{ - struct vme_bridge *bridge; - struct list_head *lm_pos = NULL; - struct vme_lm_resource *allocated_lm = NULL; - struct vme_lm_resource *lm = NULL; - struct vme_resource *resource = NULL; - - bridge = vdev->bridge; - if (bridge == NULL) { - printk(KERN_ERR "Can't find VME bus\n"); - goto err_bus; - } - - /* Loop through DMA resources */ - list_for_each(lm_pos, &bridge->lm_resources) { - lm = list_entry(lm_pos, - struct vme_lm_resource, list); - - if (lm == NULL) { - printk(KERN_ERR "Registered NULL Location Monitor resource\n"); - continue; - } - - /* Find an unlocked controller */ - mutex_lock(&lm->mtx); - if (lm->locked == 0) { - lm->locked = 1; - mutex_unlock(&lm->mtx); - allocated_lm = lm; - break; - } - mutex_unlock(&lm->mtx); - } - - /* Check to see if we found a resource */ - if (allocated_lm == NULL) - goto err_lm; - - resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); - if (resource == NULL) { - printk(KERN_ERR "Unable to allocate resource structure\n"); - goto err_alloc; - } - resource->type = VME_LM; - resource->entry = &allocated_lm->list; - - return resource; - -err_alloc: - /* Unlock image */ - mutex_lock(&lm->mtx); - lm->locked = 0; - mutex_unlock(&lm->mtx); -err_lm: -err_bus: - return NULL; -} -EXPORT_SYMBOL(vme_lm_request); - -int vme_lm_count(struct vme_resource *resource) -{ - struct vme_lm_resource *lm; - - if (resource->type != VME_LM) { - printk(KERN_ERR "Not a Location Monitor resource\n"); - return -EINVAL; - } - - lm = list_entry(resource->entry, struct vme_lm_resource, list); - - return lm->monitors; -} -EXPORT_SYMBOL(vme_lm_count); - -int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base, - u32 aspace, u32 cycle) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_lm_resource *lm; - - if (resource->type != VME_LM) { - printk(KERN_ERR "Not a Location Monitor resource\n"); - return -EINVAL; - } - - lm = list_entry(resource->entry, struct vme_lm_resource, list); - - if (bridge->lm_set == NULL) { - printk(KERN_ERR "vme_lm_set not supported\n"); - return -EINVAL; - } - - return bridge->lm_set(lm, lm_base, aspace, cycle); -} -EXPORT_SYMBOL(vme_lm_set); - -int vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base, - u32 *aspace, u32 *cycle) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_lm_resource *lm; - - if (resource->type != VME_LM) { - printk(KERN_ERR "Not a Location Monitor resource\n"); - return -EINVAL; - } - - lm = list_entry(resource->entry, struct vme_lm_resource, list); - - if (bridge->lm_get == NULL) { - printk(KERN_ERR "vme_lm_get not supported\n"); - return -EINVAL; - } - - return bridge->lm_get(lm, lm_base, aspace, cycle); -} -EXPORT_SYMBOL(vme_lm_get); - -int vme_lm_attach(struct vme_resource *resource, int monitor, - void (*callback)(int)) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_lm_resource *lm; - - if (resource->type != VME_LM) { - printk(KERN_ERR "Not a Location Monitor resource\n"); - return -EINVAL; - } - - lm = list_entry(resource->entry, struct vme_lm_resource, list); - - if (bridge->lm_attach == NULL) { - printk(KERN_ERR "vme_lm_attach not supported\n"); - return -EINVAL; - } - - return bridge->lm_attach(lm, monitor, callback); -} -EXPORT_SYMBOL(vme_lm_attach); - -int vme_lm_detach(struct vme_resource *resource, int monitor) -{ - struct vme_bridge *bridge = find_bridge(resource); - struct vme_lm_resource *lm; - - if (resource->type != VME_LM) { - printk(KERN_ERR "Not a Location Monitor resource\n"); - return -EINVAL; - } - - lm = list_entry(resource->entry, struct vme_lm_resource, list); - - if (bridge->lm_detach == NULL) { - printk(KERN_ERR "vme_lm_detach not supported\n"); - return -EINVAL; - } - - return bridge->lm_detach(lm, monitor); -} -EXPORT_SYMBOL(vme_lm_detach); - -void vme_lm_free(struct vme_resource *resource) -{ - struct vme_lm_resource *lm; - - if (resource->type != VME_LM) { - printk(KERN_ERR "Not a Location Monitor resource\n"); - return; - } - - lm = list_entry(resource->entry, struct vme_lm_resource, list); - - mutex_lock(&lm->mtx); - - /* XXX - * Check to see that there aren't any callbacks still attached, if - * there are we should probably be detaching them! - */ - - lm->locked = 0; - - mutex_unlock(&lm->mtx); - - kfree(resource); -} -EXPORT_SYMBOL(vme_lm_free); - -int vme_slot_get(struct vme_dev *vdev) -{ - struct vme_bridge *bridge; - - bridge = vdev->bridge; - if (bridge == NULL) { - printk(KERN_ERR "Can't find VME bus\n"); - return -EINVAL; - } - - if (bridge->slot_get == NULL) { - printk(KERN_WARNING "vme_slot_get not supported\n"); - return -EINVAL; - } - - return bridge->slot_get(bridge); -} -EXPORT_SYMBOL(vme_slot_get); - - -/* - Bridge Registration --------------------------------------------------- */ - -static void vme_dev_release(struct device *dev) -{ - kfree(dev_to_vme_dev(dev)); -} - -int vme_register_bridge(struct vme_bridge *bridge) -{ - int i; - int ret = -1; - - mutex_lock(&vme_buses_lock); - for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) { - if ((vme_bus_numbers & (1 << i)) == 0) { - vme_bus_numbers |= (1 << i); - bridge->num = i; - INIT_LIST_HEAD(&bridge->devices); - list_add_tail(&bridge->bus_list, &vme_bus_list); - ret = 0; - break; - } - } - mutex_unlock(&vme_buses_lock); - - return ret; -} -EXPORT_SYMBOL(vme_register_bridge); - -void vme_unregister_bridge(struct vme_bridge *bridge) -{ - struct vme_dev *vdev; - struct vme_dev *tmp; - - mutex_lock(&vme_buses_lock); - vme_bus_numbers &= ~(1 << bridge->num); - list_for_each_entry_safe(vdev, tmp, &bridge->devices, bridge_list) { - list_del(&vdev->drv_list); - list_del(&vdev->bridge_list); - device_unregister(&vdev->dev); - } - list_del(&bridge->bus_list); - mutex_unlock(&vme_buses_lock); -} -EXPORT_SYMBOL(vme_unregister_bridge); - -/* - Driver Registration --------------------------------------------------- */ - -static int __vme_register_driver_bus(struct vme_driver *drv, - struct vme_bridge *bridge, unsigned int ndevs) -{ - int err; - unsigned int i; - struct vme_dev *vdev; - struct vme_dev *tmp; - - for (i = 0; i < ndevs; i++) { - vdev = kzalloc(sizeof(struct vme_dev), GFP_KERNEL); - if (!vdev) { - err = -ENOMEM; - goto err_devalloc; - } - vdev->num = i; - vdev->bridge = bridge; - vdev->dev.platform_data = drv; - vdev->dev.release = vme_dev_release; - vdev->dev.parent = bridge->parent; - vdev->dev.bus = &vme_bus_type; - dev_set_name(&vdev->dev, "%s.%u-%u", drv->name, bridge->num, - vdev->num); - - err = device_register(&vdev->dev); - if (err) - goto err_reg; - - if (vdev->dev.platform_data) { - list_add_tail(&vdev->drv_list, &drv->devices); - list_add_tail(&vdev->bridge_list, &bridge->devices); - } else - device_unregister(&vdev->dev); - } - return 0; - -err_reg: - kfree(vdev); -err_devalloc: - list_for_each_entry_safe(vdev, tmp, &drv->devices, drv_list) { - list_del(&vdev->drv_list); - list_del(&vdev->bridge_list); - device_unregister(&vdev->dev); - } - return err; -} - -static int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs) -{ - struct vme_bridge *bridge; - int err = 0; - - mutex_lock(&vme_buses_lock); - list_for_each_entry(bridge, &vme_bus_list, bus_list) { - /* - * This cannot cause trouble as we already have vme_buses_lock - * and if the bridge is removed, it will have to go through - * vme_unregister_bridge() to do it (which calls remove() on - * the bridge which in turn tries to acquire vme_buses_lock and - * will have to wait). - */ - err = __vme_register_driver_bus(drv, bridge, ndevs); - if (err) - break; - } - mutex_unlock(&vme_buses_lock); - return err; -} - -int vme_register_driver(struct vme_driver *drv, unsigned int ndevs) -{ - int err; - - drv->driver.name = drv->name; - drv->driver.bus = &vme_bus_type; - INIT_LIST_HEAD(&drv->devices); - - err = driver_register(&drv->driver); - if (err) - return err; - - err = __vme_register_driver(drv, ndevs); - if (err) - driver_unregister(&drv->driver); - - return err; -} -EXPORT_SYMBOL(vme_register_driver); - -void vme_unregister_driver(struct vme_driver *drv) -{ - struct vme_dev *dev, *dev_tmp; - - mutex_lock(&vme_buses_lock); - list_for_each_entry_safe(dev, dev_tmp, &drv->devices, drv_list) { - list_del(&dev->drv_list); - list_del(&dev->bridge_list); - device_unregister(&dev->dev); - } - mutex_unlock(&vme_buses_lock); - - driver_unregister(&drv->driver); -} -EXPORT_SYMBOL(vme_unregister_driver); - -/* - Bus Registration ------------------------------------------------------ */ - -static int vme_bus_match(struct device *dev, struct device_driver *drv) -{ - struct vme_driver *vme_drv; - - vme_drv = container_of(drv, struct vme_driver, driver); - - if (dev->platform_data == vme_drv) { - struct vme_dev *vdev = dev_to_vme_dev(dev); - - if (vme_drv->match && vme_drv->match(vdev)) - return 1; - - dev->platform_data = NULL; - } - return 0; -} - -static int vme_bus_probe(struct device *dev) -{ - int retval = -ENODEV; - struct vme_driver *driver; - struct vme_dev *vdev = dev_to_vme_dev(dev); - - driver = dev->platform_data; - - if (driver->probe != NULL) - retval = driver->probe(vdev); - - return retval; -} - -static int vme_bus_remove(struct device *dev) -{ - int retval = -ENODEV; - struct vme_driver *driver; - struct vme_dev *vdev = dev_to_vme_dev(dev); - - driver = dev->platform_data; - - if (driver->remove != NULL) - retval = driver->remove(vdev); - - return retval; -} - -struct bus_type vme_bus_type = { - .name = "vme", - .match = vme_bus_match, - .probe = vme_bus_probe, - .remove = vme_bus_remove, -}; -EXPORT_SYMBOL(vme_bus_type); - -static int __init vme_init(void) -{ - return bus_register(&vme_bus_type); -} - -static void __exit vme_exit(void) -{ - bus_unregister(&vme_bus_type); -} - -MODULE_DESCRIPTION("VME bridge driver framework"); -MODULE_AUTHOR("Martyn Welch id.num >= USER_BUS_MAX) - return 0; - return 1; - } - -The '.probe' element should contain a pointer to the probe routine. The -probe routine is passed a 'struct vme_dev' pointer as an argument. The -'struct vme_dev' structure looks like the following: - - struct vme_dev { - int num; - struct vme_bridge *bridge; - struct device dev; - struct list_head drv_list; - struct list_head bridge_list; - }; - -Here, the 'num' field refers to the sequential device ID for this specific -driver. The bridge number (or bus number) can be accessed using -dev->bridge->num. - -A function is also provided to unregister the driver from the VME core and is -usually called from the device driver's exit routine: - - void vme_unregister_driver (struct vme_driver *driver); - - -Resource management -=================== - -Once a driver has registered with the VME core the provided match routine will -be called the number of times specified during the registration. If a match -succeeds, a non-zero value should be returned. A zero return value indicates -failure. For all successful matches, the probe routine of the corresponding -driver is called. The probe routine is passed a pointer to the devices -device structure. This pointer should be saved, it will be required for -requesting VME resources. - -The driver can request ownership of one or more master windows, slave windows -and/or dma channels. Rather than allowing the device driver to request a -specific window or DMA channel (which may be used by a different driver) this -driver allows a resource to be assigned based on the required attributes of the -driver in question: - - struct vme_resource * vme_master_request(struct vme_dev *dev, - u32 aspace, u32 cycle, u32 width); - - struct vme_resource * vme_slave_request(struct vme_dev *dev, u32 aspace, - u32 cycle); - - struct vme_resource *vme_dma_request(struct vme_dev *dev, u32 route); - -For slave windows these attributes are split into the VME address spaces that -need to be accessed in 'aspace' and VME bus cycle types required in 'cycle'. -Master windows add a further set of attributes in 'width' specifying the -required data transfer widths. These attributes are defined as bitmasks and as -such any combination of the attributes can be requested for a single window, -the core will assign a window that meets the requirements, returning a pointer -of type vme_resource that should be used to identify the allocated resource -when it is used. For DMA controllers, the request function requires the -potential direction of any transfers to be provided in the route attributes. -This is typically VME-to-MEM and/or MEM-to-VME, though some hardware can -support VME-to-VME and MEM-to-MEM transfers as well as test pattern generation. -If an unallocated window fitting the requirements can not be found a NULL -pointer will be returned. - -Functions are also provided to free window allocations once they are no longer -required. These functions should be passed the pointer to the resource provided -during resource allocation: - - void vme_master_free(struct vme_resource *res); - - void vme_slave_free(struct vme_resource *res); - - void vme_dma_free(struct vme_resource *res); - - -Master windows -============== - -Master windows provide access from the local processor[s] out onto the VME bus. -The number of windows available and the available access modes is dependent on -the underlying chipset. A window must be configured before it can be used. - - -Master window configuration ---------------------------- - -Once a master window has been assigned the following functions can be used to -configure it and retrieve the current settings: - - int vme_master_set (struct vme_resource *res, int enabled, - unsigned long long base, unsigned long long size, u32 aspace, - u32 cycle, u32 width); - - int vme_master_get (struct vme_resource *res, int *enabled, - unsigned long long *base, unsigned long long *size, u32 *aspace, - u32 *cycle, u32 *width); - -The address spaces, transfer widths and cycle types are the same as described -under resource management, however some of the options are mutually exclusive. -For example, only one address space may be specified. - -These functions return 0 on success or an error code should the call fail. - - -Master window access --------------------- - -The following functions can be used to read from and write to configured master -windows. These functions return the number of bytes copied: - - ssize_t vme_master_read(struct vme_resource *res, void *buf, - size_t count, loff_t offset); - - ssize_t vme_master_write(struct vme_resource *res, void *buf, - size_t count, loff_t offset); - -In addition to simple reads and writes, a function is provided to do a -read-modify-write transaction. This function returns the original value of the -VME bus location : - - unsigned int vme_master_rmw (struct vme_resource *res, - unsigned int mask, unsigned int compare, unsigned int swap, - loff_t offset); - -This functions by reading the offset, applying the mask. If the bits selected in -the mask match with the values of the corresponding bits in the compare field, -the value of swap is written the specified offset. - - -Slave windows -============= - -Slave windows provide devices on the VME bus access into mapped portions of the -local memory. The number of windows available and the access modes that can be -used is dependent on the underlying chipset. A window must be configured before -it can be used. - - -Slave window configuration --------------------------- - -Once a slave window has been assigned the following functions can be used to -configure it and retrieve the current settings: - - int vme_slave_set (struct vme_resource *res, int enabled, - unsigned long long base, unsigned long long size, - dma_addr_t mem, u32 aspace, u32 cycle); - - int vme_slave_get (struct vme_resource *res, int *enabled, - unsigned long long *base, unsigned long long *size, - dma_addr_t *mem, u32 *aspace, u32 *cycle); - -The address spaces, transfer widths and cycle types are the same as described -under resource management, however some of the options are mutually exclusive. -For example, only one address space may be specified. - -These functions return 0 on success or an error code should the call fail. - - -Slave window buffer allocation ------------------------------- - -Functions are provided to allow the user to allocate and free a contiguous -buffers which will be accessible by the VME bridge. These functions do not have -to be used, other methods can be used to allocate a buffer, though care must be -taken to ensure that they are contiguous and accessible by the VME bridge: - - void * vme_alloc_consistent(struct vme_resource *res, size_t size, - dma_addr_t *mem); - - void vme_free_consistent(struct vme_resource *res, size_t size, - void *virt, dma_addr_t mem); - - -Slave window access -------------------- - -Slave windows map local memory onto the VME bus, the standard methods for -accessing memory should be used. - - -DMA channels -============ - -The VME DMA transfer provides the ability to run link-list DMA transfers. The -API introduces the concept of DMA lists. Each DMA list is a link-list which can -be passed to a DMA controller. Multiple lists can be created, extended, -executed, reused and destroyed. - - -List Management ---------------- - -The following functions are provided to create and destroy DMA lists. Execution -of a list will not automatically destroy the list, thus enabling a list to be -reused for repetitive tasks: - - struct vme_dma_list *vme_new_dma_list(struct vme_resource *res); - - int vme_dma_list_free(struct vme_dma_list *list); - - -List Population ---------------- - -An item can be added to a list using the following function ( the source and -destination attributes need to be created before calling this function, this is -covered under "Transfer Attributes"): - - int vme_dma_list_add(struct vme_dma_list *list, - struct vme_dma_attr *src, struct vme_dma_attr *dest, - size_t count); - -NOTE: The detailed attributes of the transfers source and destination - are not checked until an entry is added to a DMA list, the request - for a DMA channel purely checks the directions in which the - controller is expected to transfer data. As a result it is - possible for this call to return an error, for example if the - source or destination is in an unsupported VME address space. - -Transfer Attributes -------------------- - -The attributes for the source and destination are handled separately from adding -an item to a list. This is due to the diverse attributes required for each type -of source and destination. There are functions to create attributes for PCI, VME -and pattern sources and destinations (where appropriate): - -Pattern source: - - struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type); - -PCI source or destination: - - struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t mem); - -VME source or destination: - - struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long base, - u32 aspace, u32 cycle, u32 width); - -The following function should be used to free an attribute: - - void vme_dma_free_attribute(struct vme_dma_attr *attr); - - -List Execution --------------- - -The following function queues a list for execution. The function will return -once the list has been executed: - - int vme_dma_list_exec(struct vme_dma_list *list); - - -Interrupts -========== - -The VME API provides functions to attach and detach callbacks to specific VME -level and status ID combinations and for the generation of VME interrupts with -specific VME level and status IDs. - - -Attaching Interrupt Handlers ----------------------------- - -The following functions can be used to attach and free a specific VME level and -status ID combination. Any given combination can only be assigned a single -callback function. A void pointer parameter is provided, the value of which is -passed to the callback function, the use of this pointer is user undefined: - - int vme_irq_request(struct vme_dev *dev, int level, int statid, - void (*callback)(int, int, void *), void *priv); - - void vme_irq_free(struct vme_dev *dev, int level, int statid); - -The callback parameters are as follows. Care must be taken in writing a callback -function, callback functions run in interrupt context: - - void callback(int level, int statid, void *priv); - - -Interrupt Generation --------------------- - -The following function can be used to generate a VME interrupt at a given VME -level and VME status ID: - - int vme_irq_generate(struct vme_dev *dev, int level, int statid); - - -Location monitors -================= - -The VME API provides the following functionality to configure the location -monitor. - - -Location Monitor Management ---------------------------- - -The following functions are provided to request the use of a block of location -monitors and to free them after they are no longer required: - - struct vme_resource * vme_lm_request(struct vme_dev *dev); - - void vme_lm_free(struct vme_resource * res); - -Each block may provide a number of location monitors, monitoring adjacent -locations. The following function can be used to determine how many locations -are provided: - - int vme_lm_count(struct vme_resource * res); - - -Location Monitor Configuration ------------------------------- - -Once a bank of location monitors has been allocated, the following functions -are provided to configure the location and mode of the location monitor: - - int vme_lm_set(struct vme_resource *res, unsigned long long base, - u32 aspace, u32 cycle); - - int vme_lm_get(struct vme_resource *res, unsigned long long *base, - u32 *aspace, u32 *cycle); - - -Location Monitor Use --------------------- - -The following functions allow a callback to be attached and detached from each -location monitor location. Each location monitor can monitor a number of -adjacent locations: - - int vme_lm_attach(struct vme_resource *res, int num, - void (*callback)(int)); - - int vme_lm_detach(struct vme_resource *res, int num); - -The callback function is declared as follows. - - void callback(int num); - - -Slot Detection -============== - -This function returns the slot ID of the provided bridge. - - int vme_slot_get(struct vme_dev *dev); diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h deleted file mode 100644 index 934949abd745..000000000000 --- a/drivers/staging/vme/vme_bridge.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef _VME_BRIDGE_H_ -#define _VME_BRIDGE_H_ - -#define VME_CRCSR_BUF_SIZE (508*1024) -/* - * Resource structures - */ -struct vme_master_resource { - struct list_head list; - struct vme_bridge *parent; - /* - * We are likely to need to access the VME bus in interrupt context, so - * protect master routines with a spinlock rather than a mutex. - */ - spinlock_t lock; - int locked; - int number; - u32 address_attr; - u32 cycle_attr; - u32 width_attr; - struct resource bus_resource; - void __iomem *kern_base; -}; - -struct vme_slave_resource { - struct list_head list; - struct vme_bridge *parent; - struct mutex mtx; - int locked; - int number; - u32 address_attr; - u32 cycle_attr; -}; - -struct vme_dma_pattern { - u32 pattern; - u32 type; -}; - -struct vme_dma_pci { - dma_addr_t address; -}; - -struct vme_dma_vme { - unsigned long long address; - u32 aspace; - u32 cycle; - u32 dwidth; -}; - -struct vme_dma_list { - struct list_head list; - struct vme_dma_resource *parent; - struct list_head entries; - struct mutex mtx; -}; - -struct vme_dma_resource { - struct list_head list; - struct vme_bridge *parent; - struct mutex mtx; - int locked; - int number; - struct list_head pending; - struct list_head running; - u32 route_attr; -}; - -struct vme_lm_resource { - struct list_head list; - struct vme_bridge *parent; - struct mutex mtx; - int locked; - int number; - int monitors; -}; - -struct vme_bus_error { - struct list_head list; - unsigned long long address; - u32 attributes; -}; - -struct vme_callback { - void (*func)(int, int, void*); - void *priv_data; -}; - -struct vme_irq { - int count; - struct vme_callback callback[255]; -}; - -/* Allow 16 characters for name (including null character) */ -#define VMENAMSIZ 16 - -/* This structure stores all the information about one bridge - * The structure should be dynamically allocated by the driver and one instance - * of the structure should be present for each VME chip present in the system. - */ -struct vme_bridge { - char name[VMENAMSIZ]; - int num; - struct list_head master_resources; - struct list_head slave_resources; - struct list_head dma_resources; - struct list_head lm_resources; - - struct list_head vme_errors; /* List for errors generated on VME */ - struct list_head devices; /* List of devices on this bridge */ - - /* Bridge Info - XXX Move to private structure? */ - struct device *parent; /* Parent device (eg. pdev->dev for PCI) */ - void *driver_priv; /* Private pointer for the bridge driver */ - struct list_head bus_list; /* list of VME buses */ - - /* Interrupt callbacks */ - struct vme_irq irq[7]; - /* Locking for VME irq callback configuration */ - struct mutex irq_mtx; - - /* Slave Functions */ - int (*slave_get) (struct vme_slave_resource *, int *, - unsigned long long *, unsigned long long *, dma_addr_t *, - u32 *, u32 *); - int (*slave_set) (struct vme_slave_resource *, int, unsigned long long, - unsigned long long, dma_addr_t, u32, u32); - - /* Master Functions */ - int (*master_get) (struct vme_master_resource *, int *, - unsigned long long *, unsigned long long *, u32 *, u32 *, - u32 *); - int (*master_set) (struct vme_master_resource *, int, - unsigned long long, unsigned long long, u32, u32, u32); - ssize_t (*master_read) (struct vme_master_resource *, void *, size_t, - loff_t); - ssize_t (*master_write) (struct vme_master_resource *, void *, size_t, - loff_t); - unsigned int (*master_rmw) (struct vme_master_resource *, unsigned int, - unsigned int, unsigned int, loff_t); - - /* DMA Functions */ - int (*dma_list_add) (struct vme_dma_list *, struct vme_dma_attr *, - struct vme_dma_attr *, size_t); - int (*dma_list_exec) (struct vme_dma_list *); - int (*dma_list_empty) (struct vme_dma_list *); - - /* Interrupt Functions */ - void (*irq_set) (struct vme_bridge *, int, int, int); - int (*irq_generate) (struct vme_bridge *, int, int); - - /* Location monitor functions */ - int (*lm_set) (struct vme_lm_resource *, unsigned long long, u32, u32); - int (*lm_get) (struct vme_lm_resource *, unsigned long long *, u32 *, - u32 *); - int (*lm_attach) (struct vme_lm_resource *, int, void (*callback)(int)); - int (*lm_detach) (struct vme_lm_resource *, int); - - /* CR/CSR space functions */ - int (*slot_get) (struct vme_bridge *); - - /* Bridge parent interface */ - void *(*alloc_consistent)(struct device *dev, size_t size, - dma_addr_t *dma); - void (*free_consistent)(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma); -}; - -void vme_irq_handler(struct vme_bridge *, int, int); - -int vme_register_bridge(struct vme_bridge *); -void vme_unregister_bridge(struct vme_bridge *); - -#endif /* _VME_BRIDGE_H_ */ diff --git a/drivers/vme/Kconfig b/drivers/vme/Kconfig new file mode 100644 index 000000000000..c5c22465a805 --- /dev/null +++ b/drivers/vme/Kconfig @@ -0,0 +1,19 @@ +# +# VME configuration. +# + +menuconfig VME_BUS + tristate "VME bridge support" + depends on PCI + ---help--- + If you say Y here you get support for the VME bridge Framework. + +if VME_BUS + +source "drivers/vme/bridges/Kconfig" + +source "drivers/vme/boards/Kconfig" + +source "drivers/staging/vme/devices/Kconfig" + +endif # VME diff --git a/drivers/vme/Makefile b/drivers/vme/Makefile new file mode 100644 index 000000000000..d7bfcb9fd5a1 --- /dev/null +++ b/drivers/vme/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the VME bridge device drivers. +# +obj-$(CONFIG_VME_BUS) += vme.o + +obj-y += bridges/ +obj-y += boards/ diff --git a/drivers/vme/boards/Kconfig b/drivers/vme/boards/Kconfig new file mode 100644 index 000000000000..761631353527 --- /dev/null +++ b/drivers/vme/boards/Kconfig @@ -0,0 +1,9 @@ +comment "VME Board Drivers" + +config VMIVME_7805 + tristate "VMIVME-7805" + help + If you say Y here you get support for the VMIVME-7805 board. + This board has an additional control interface to the Universe II + chip. This driver has to be included if you want to access VME bus + with VMIVME-7805 board. diff --git a/drivers/vme/boards/Makefile b/drivers/vme/boards/Makefile new file mode 100644 index 000000000000..43658340885d --- /dev/null +++ b/drivers/vme/boards/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the VME board drivers. +# + +obj-$(CONFIG_VMIVME_7805) += vme_vmivme7805.o diff --git a/drivers/vme/boards/vme_vmivme7805.c b/drivers/vme/boards/vme_vmivme7805.c new file mode 100644 index 000000000000..8e05bb4e135a --- /dev/null +++ b/drivers/vme/boards/vme_vmivme7805.c @@ -0,0 +1,123 @@ +/* + * Support for the VMIVME-7805 board access to the Universe II bridge. + * + * Author: Arthur Benilov + * Copyright 2010 Ion Beam Application, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include "vme_vmivme7805.h" + +static int __init vmic_init(void); +static int vmic_probe(struct pci_dev *, const struct pci_device_id *); +static void vmic_remove(struct pci_dev *); +static void __exit vmic_exit(void); + +/** Base address to access FPGA register */ +static void *vmic_base; + +static const char driver_name[] = "vmivme_7805"; + +static DEFINE_PCI_DEVICE_TABLE(vmic_ids) = { + { PCI_DEVICE(PCI_VENDOR_ID_VMIC, PCI_DEVICE_ID_VTIMR) }, + { }, +}; + +static struct pci_driver vmic_driver = { + .name = driver_name, + .id_table = vmic_ids, + .probe = vmic_probe, + .remove = vmic_remove, +}; + +static int __init vmic_init(void) +{ + return pci_register_driver(&vmic_driver); +} + +static int vmic_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int retval; + u32 data; + + /* Enable the device */ + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "Unable to enable device\n"); + goto err; + } + + /* Map Registers */ + retval = pci_request_regions(pdev, driver_name); + if (retval) { + dev_err(&pdev->dev, "Unable to reserve resources\n"); + goto err_resource; + } + + /* Map registers in BAR 0 */ + vmic_base = ioremap_nocache(pci_resource_start(pdev, 0), 16); + if (!vmic_base) { + dev_err(&pdev->dev, "Unable to remap CRG region\n"); + retval = -EIO; + goto err_remap; + } + + /* Clear the FPGA VME IF contents */ + iowrite32(0, vmic_base + VME_CONTROL); + + /* Clear any initial BERR */ + data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF; + data |= BM_VME_CONTROL_BERRST; + iowrite32(data, vmic_base + VME_CONTROL); + + /* Enable the vme interface and byte swapping */ + data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF; + data = data | BM_VME_CONTROL_MASTER_ENDIAN | + BM_VME_CONTROL_SLAVE_ENDIAN | + BM_VME_CONTROL_ABLE | + BM_VME_CONTROL_BERRI | + BM_VME_CONTROL_BPENA | + BM_VME_CONTROL_VBENA; + iowrite32(data, vmic_base + VME_CONTROL); + + return 0; + +err_remap: + pci_release_regions(pdev); +err_resource: + pci_disable_device(pdev); +err: + return retval; +} + +static void vmic_remove(struct pci_dev *pdev) +{ + iounmap(vmic_base); + pci_release_regions(pdev); + pci_disable_device(pdev); + +} + +static void __exit vmic_exit(void) +{ + pci_unregister_driver(&vmic_driver); +} + +MODULE_DESCRIPTION("VMIVME-7805 board support driver"); +MODULE_AUTHOR("Arthur Benilov "); +MODULE_LICENSE("GPL"); + +module_init(vmic_init); +module_exit(vmic_exit); + diff --git a/drivers/vme/boards/vme_vmivme7805.h b/drivers/vme/boards/vme_vmivme7805.h new file mode 100644 index 000000000000..44c2c449808c --- /dev/null +++ b/drivers/vme/boards/vme_vmivme7805.h @@ -0,0 +1,37 @@ +/* + * vmivme_7805.h + * + * Support for the VMIVME-7805 board access to the Universe II bridge. + * + * Author: Arthur Benilov + * Copyright 2010 Ion Beam Application, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +#ifndef _VMIVME_7805_H +#define _VMIVME_7805_H + +#ifndef PCI_VENDOR_ID_VMIC +#define PCI_VENDOR_ID_VMIC 0x114A +#endif + +#ifndef PCI_DEVICE_ID_VTIMR +#define PCI_DEVICE_ID_VTIMR 0x0004 +#endif + +#define VME_CONTROL 0x0000 +#define BM_VME_CONTROL_MASTER_ENDIAN 0x0001 +#define BM_VME_CONTROL_SLAVE_ENDIAN 0x0002 +#define BM_VME_CONTROL_ABLE 0x0004 +#define BM_VME_CONTROL_BERRI 0x0040 +#define BM_VME_CONTROL_BERRST 0x0080 +#define BM_VME_CONTROL_BPENA 0x0400 +#define BM_VME_CONTROL_VBENA 0x0800 + +#endif /* _VMIVME_7805_H */ + diff --git a/drivers/vme/bridges/Kconfig b/drivers/vme/bridges/Kconfig new file mode 100644 index 000000000000..9331064e0476 --- /dev/null +++ b/drivers/vme/bridges/Kconfig @@ -0,0 +1,15 @@ +comment "VME Bridge Drivers" + +config VME_CA91CX42 + tristate "Universe II" + depends on VIRT_TO_BUS + help + If you say Y here you get support for the Tundra CA91C142 + (Universe II) VME bridge chip. + +config VME_TSI148 + tristate "Tempe" + depends on VIRT_TO_BUS + help + If you say Y here you get support for the Tundra TSI148 VME bridge + chip. diff --git a/drivers/vme/bridges/Makefile b/drivers/vme/bridges/Makefile new file mode 100644 index 000000000000..59638afcd502 --- /dev/null +++ b/drivers/vme/bridges/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_VME_CA91CX42) += vme_ca91cx42.o +obj-$(CONFIG_VME_TSI148) += vme_tsi148.o diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c new file mode 100644 index 000000000000..a3c0f84e2fa1 --- /dev/null +++ b/drivers/vme/bridges/vme_ca91cx42.c @@ -0,0 +1,1959 @@ +/* + * Support for the Tundra Universe I/II VME-PCI Bridge Chips + * + * Author: Martyn Welch + * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. + * + * Based on work by Tom Armistead and Ajit Prem + * Copyright 2004 Motorola Inc. + * + * Derived from ca91c042.c by Michael Wyrick + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../vme_bridge.h" +#include "vme_ca91cx42.h" + +static int __init ca91cx42_init(void); +static int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *); +static void ca91cx42_remove(struct pci_dev *); +static void __exit ca91cx42_exit(void); + +/* Module parameters */ +static int geoid; + +static const char driver_name[] = "vme_ca91cx42"; + +static DEFINE_PCI_DEVICE_TABLE(ca91cx42_ids) = { + { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) }, + { }, +}; + +static struct pci_driver ca91cx42_driver = { + .name = driver_name, + .id_table = ca91cx42_ids, + .probe = ca91cx42_probe, + .remove = ca91cx42_remove, +}; + +static u32 ca91cx42_DMA_irqhandler(struct ca91cx42_driver *bridge) +{ + wake_up(&bridge->dma_queue); + + return CA91CX42_LINT_DMA; +} + +static u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat) +{ + int i; + u32 serviced = 0; + + for (i = 0; i < 4; i++) { + if (stat & CA91CX42_LINT_LM[i]) { + /* We only enable interrupts if the callback is set */ + bridge->lm_callback[i](i); + serviced |= CA91CX42_LINT_LM[i]; + } + } + + return serviced; +} + +/* XXX This needs to be split into 4 queues */ +static u32 ca91cx42_MB_irqhandler(struct ca91cx42_driver *bridge, int mbox_mask) +{ + wake_up(&bridge->mbox_queue); + + return CA91CX42_LINT_MBOX; +} + +static u32 ca91cx42_IACK_irqhandler(struct ca91cx42_driver *bridge) +{ + wake_up(&bridge->iack_queue); + + return CA91CX42_LINT_SW_IACK; +} + +static u32 ca91cx42_VERR_irqhandler(struct vme_bridge *ca91cx42_bridge) +{ + int val; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + val = ioread32(bridge->base + DGCS); + + if (!(val & 0x00000800)) { + dev_err(ca91cx42_bridge->parent, "ca91cx42_VERR_irqhandler DMA " + "Read Error DGCS=%08X\n", val); + } + + return CA91CX42_LINT_VERR; +} + +static u32 ca91cx42_LERR_irqhandler(struct vme_bridge *ca91cx42_bridge) +{ + int val; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + val = ioread32(bridge->base + DGCS); + + if (!(val & 0x00000800)) + dev_err(ca91cx42_bridge->parent, "ca91cx42_LERR_irqhandler DMA " + "Read Error DGCS=%08X\n", val); + + return CA91CX42_LINT_LERR; +} + + +static u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge, + int stat) +{ + int vec, i, serviced = 0; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + + for (i = 7; i > 0; i--) { + if (stat & (1 << i)) { + vec = ioread32(bridge->base + + CA91CX42_V_STATID[i]) & 0xff; + + vme_irq_handler(ca91cx42_bridge, i, vec); + + serviced |= (1 << i); + } + } + + return serviced; +} + +static irqreturn_t ca91cx42_irqhandler(int irq, void *ptr) +{ + u32 stat, enable, serviced = 0; + struct vme_bridge *ca91cx42_bridge; + struct ca91cx42_driver *bridge; + + ca91cx42_bridge = ptr; + + bridge = ca91cx42_bridge->driver_priv; + + enable = ioread32(bridge->base + LINT_EN); + stat = ioread32(bridge->base + LINT_STAT); + + /* Only look at unmasked interrupts */ + stat &= enable; + + if (unlikely(!stat)) + return IRQ_NONE; + + if (stat & CA91CX42_LINT_DMA) + serviced |= ca91cx42_DMA_irqhandler(bridge); + if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | + CA91CX42_LINT_LM3)) + serviced |= ca91cx42_LM_irqhandler(bridge, stat); + if (stat & CA91CX42_LINT_MBOX) + serviced |= ca91cx42_MB_irqhandler(bridge, stat); + if (stat & CA91CX42_LINT_SW_IACK) + serviced |= ca91cx42_IACK_irqhandler(bridge); + if (stat & CA91CX42_LINT_VERR) + serviced |= ca91cx42_VERR_irqhandler(ca91cx42_bridge); + if (stat & CA91CX42_LINT_LERR) + serviced |= ca91cx42_LERR_irqhandler(ca91cx42_bridge); + if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 | + CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 | + CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 | + CA91CX42_LINT_VIRQ7)) + serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat); + + /* Clear serviced interrupts */ + iowrite32(serviced, bridge->base + LINT_STAT); + + return IRQ_HANDLED; +} + +static int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge) +{ + int result, tmp; + struct pci_dev *pdev; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + /* Need pdev */ + pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); + + /* Initialise list for VME bus errors */ + INIT_LIST_HEAD(&ca91cx42_bridge->vme_errors); + + mutex_init(&ca91cx42_bridge->irq_mtx); + + /* Disable interrupts from PCI to VME */ + iowrite32(0, bridge->base + VINT_EN); + + /* Disable PCI interrupts */ + iowrite32(0, bridge->base + LINT_EN); + /* Clear Any Pending PCI Interrupts */ + iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); + + result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED, + driver_name, ca91cx42_bridge); + if (result) { + dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n", + pdev->irq); + return result; + } + + /* Ensure all interrupts are mapped to PCI Interrupt 0 */ + iowrite32(0, bridge->base + LINT_MAP0); + iowrite32(0, bridge->base + LINT_MAP1); + iowrite32(0, bridge->base + LINT_MAP2); + + /* Enable DMA, mailbox & LM Interrupts */ + tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 | + CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK | + CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA; + + iowrite32(tmp, bridge->base + LINT_EN); + + return 0; +} + +static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, + struct pci_dev *pdev) +{ + /* Disable interrupts from PCI to VME */ + iowrite32(0, bridge->base + VINT_EN); + + /* Disable PCI interrupts */ + iowrite32(0, bridge->base + LINT_EN); + /* Clear Any Pending PCI Interrupts */ + iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); + + free_irq(pdev->irq, pdev); +} + +static int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level) +{ + u32 tmp; + + tmp = ioread32(bridge->base + LINT_STAT); + + if (tmp & (1 << level)) + return 0; + else + return 1; +} + +/* + * Set up an VME interrupt + */ +static void ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, + int state, int sync) + +{ + struct pci_dev *pdev; + u32 tmp; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + /* Enable IRQ level */ + tmp = ioread32(bridge->base + LINT_EN); + + if (state == 0) + tmp &= ~CA91CX42_LINT_VIRQ[level]; + else + tmp |= CA91CX42_LINT_VIRQ[level]; + + iowrite32(tmp, bridge->base + LINT_EN); + + if ((state == 0) && (sync != 0)) { + pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, + dev); + + synchronize_irq(pdev->irq); + } +} + +static int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level, + int statid) +{ + u32 tmp; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + /* Universe can only generate even vectors */ + if (statid & 1) + return -EINVAL; + + mutex_lock(&bridge->vme_int); + + tmp = ioread32(bridge->base + VINT_EN); + + /* Set Status/ID */ + iowrite32(statid << 24, bridge->base + STATID); + + /* Assert VMEbus IRQ */ + tmp = tmp | (1 << (level + 24)); + iowrite32(tmp, bridge->base + VINT_EN); + + /* Wait for IACK */ + wait_event_interruptible(bridge->iack_queue, + ca91cx42_iack_received(bridge, level)); + + /* Return interrupt to low state */ + tmp = ioread32(bridge->base + VINT_EN); + tmp = tmp & ~(1 << (level + 24)); + iowrite32(tmp, bridge->base + VINT_EN); + + mutex_unlock(&bridge->vme_int); + + return 0; +} + +static int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, + unsigned long long vme_base, unsigned long long size, + dma_addr_t pci_base, u32 aspace, u32 cycle) +{ + unsigned int i, addr = 0, granularity; + unsigned int temp_ctl = 0; + unsigned int vme_bound, pci_offset; + struct vme_bridge *ca91cx42_bridge; + struct ca91cx42_driver *bridge; + + ca91cx42_bridge = image->parent; + + bridge = ca91cx42_bridge->driver_priv; + + i = image->number; + + switch (aspace) { + case VME_A16: + addr |= CA91CX42_VSI_CTL_VAS_A16; + break; + case VME_A24: + addr |= CA91CX42_VSI_CTL_VAS_A24; + break; + case VME_A32: + addr |= CA91CX42_VSI_CTL_VAS_A32; + break; + case VME_USER1: + addr |= CA91CX42_VSI_CTL_VAS_USER1; + break; + case VME_USER2: + addr |= CA91CX42_VSI_CTL_VAS_USER2; + break; + case VME_A64: + case VME_CRCSR: + case VME_USER3: + case VME_USER4: + default: + dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); + return -EINVAL; + break; + } + + /* + * Bound address is a valid address for the window, adjust + * accordingly + */ + vme_bound = vme_base + size; + pci_offset = pci_base - vme_base; + + if ((i == 0) || (i == 4)) + granularity = 0x1000; + else + granularity = 0x10000; + + if (vme_base & (granularity - 1)) { + dev_err(ca91cx42_bridge->parent, "Invalid VME base " + "alignment\n"); + return -EINVAL; + } + if (vme_bound & (granularity - 1)) { + dev_err(ca91cx42_bridge->parent, "Invalid VME bound " + "alignment\n"); + return -EINVAL; + } + if (pci_offset & (granularity - 1)) { + dev_err(ca91cx42_bridge->parent, "Invalid PCI Offset " + "alignment\n"); + return -EINVAL; + } + + /* Disable while we are mucking around */ + temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); + temp_ctl &= ~CA91CX42_VSI_CTL_EN; + iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); + + /* Setup mapping */ + iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]); + iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]); + iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]); + + /* Setup address space */ + temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; + temp_ctl |= addr; + + /* Setup cycle types */ + temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); + if (cycle & VME_SUPER) + temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; + if (cycle & VME_USER) + temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; + if (cycle & VME_PROG) + temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; + if (cycle & VME_DATA) + temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; + + /* Write ctl reg without enable */ + iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); + + if (enabled) + temp_ctl |= CA91CX42_VSI_CTL_EN; + + iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]); + + return 0; +} + +static int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, + dma_addr_t *pci_base, u32 *aspace, u32 *cycle) +{ + unsigned int i, granularity = 0, ctl = 0; + unsigned long long vme_bound, pci_offset; + struct ca91cx42_driver *bridge; + + bridge = image->parent->driver_priv; + + i = image->number; + + if ((i == 0) || (i == 4)) + granularity = 0x1000; + else + granularity = 0x10000; + + /* Read Registers */ + ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]); + + *vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]); + vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]); + pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]); + + *pci_base = (dma_addr_t)vme_base + pci_offset; + *size = (unsigned long long)((vme_bound - *vme_base) + granularity); + + *enabled = 0; + *aspace = 0; + *cycle = 0; + + if (ctl & CA91CX42_VSI_CTL_EN) + *enabled = 1; + + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) + *aspace = VME_A16; + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) + *aspace = VME_A24; + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) + *aspace = VME_A32; + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) + *aspace = VME_USER1; + if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) + *aspace = VME_USER2; + + if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) + *cycle |= VME_SUPER; + if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) + *cycle |= VME_USER; + if (ctl & CA91CX42_VSI_CTL_PGM_PGM) + *cycle |= VME_PROG; + if (ctl & CA91CX42_VSI_CTL_PGM_DATA) + *cycle |= VME_DATA; + + return 0; +} + +/* + * Allocate and map PCI Resource + */ +static int ca91cx42_alloc_resource(struct vme_master_resource *image, + unsigned long long size) +{ + unsigned long long existing_size; + int retval = 0; + struct pci_dev *pdev; + struct vme_bridge *ca91cx42_bridge; + + ca91cx42_bridge = image->parent; + + /* Find pci_dev container of dev */ + if (ca91cx42_bridge->parent == NULL) { + dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); + return -EINVAL; + } + pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); + + existing_size = (unsigned long long)(image->bus_resource.end - + image->bus_resource.start); + + /* If the existing size is OK, return */ + if (existing_size == (size - 1)) + return 0; + + if (existing_size != 0) { + iounmap(image->kern_base); + image->kern_base = NULL; + kfree(image->bus_resource.name); + release_resource(&image->bus_resource); + memset(&image->bus_resource, 0, sizeof(struct resource)); + } + + if (image->bus_resource.name == NULL) { + image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); + if (image->bus_resource.name == NULL) { + dev_err(ca91cx42_bridge->parent, "Unable to allocate " + "memory for resource name\n"); + retval = -ENOMEM; + goto err_name; + } + } + + sprintf((char *)image->bus_resource.name, "%s.%d", + ca91cx42_bridge->name, image->number); + + image->bus_resource.start = 0; + image->bus_resource.end = (unsigned long)size; + image->bus_resource.flags = IORESOURCE_MEM; + + retval = pci_bus_alloc_resource(pdev->bus, + &image->bus_resource, size, size, PCIBIOS_MIN_MEM, + 0, NULL, NULL); + if (retval) { + dev_err(ca91cx42_bridge->parent, "Failed to allocate mem " + "resource for window %d size 0x%lx start 0x%lx\n", + image->number, (unsigned long)size, + (unsigned long)image->bus_resource.start); + goto err_resource; + } + + image->kern_base = ioremap_nocache( + image->bus_resource.start, size); + if (image->kern_base == NULL) { + dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); + retval = -ENOMEM; + goto err_remap; + } + + return 0; + +err_remap: + release_resource(&image->bus_resource); +err_resource: + kfree(image->bus_resource.name); + memset(&image->bus_resource, 0, sizeof(struct resource)); +err_name: + return retval; +} + +/* + * Free and unmap PCI Resource + */ +static void ca91cx42_free_resource(struct vme_master_resource *image) +{ + iounmap(image->kern_base); + image->kern_base = NULL; + release_resource(&image->bus_resource); + kfree(image->bus_resource.name); + memset(&image->bus_resource, 0, sizeof(struct resource)); +} + + +static int ca91cx42_master_set(struct vme_master_resource *image, int enabled, + unsigned long long vme_base, unsigned long long size, u32 aspace, + u32 cycle, u32 dwidth) +{ + int retval = 0; + unsigned int i, granularity = 0; + unsigned int temp_ctl = 0; + unsigned long long pci_bound, vme_offset, pci_base; + struct vme_bridge *ca91cx42_bridge; + struct ca91cx42_driver *bridge; + + ca91cx42_bridge = image->parent; + + bridge = ca91cx42_bridge->driver_priv; + + i = image->number; + + if ((i == 0) || (i == 4)) + granularity = 0x1000; + else + granularity = 0x10000; + + /* Verify input data */ + if (vme_base & (granularity - 1)) { + dev_err(ca91cx42_bridge->parent, "Invalid VME Window " + "alignment\n"); + retval = -EINVAL; + goto err_window; + } + if (size & (granularity - 1)) { + dev_err(ca91cx42_bridge->parent, "Invalid VME Window " + "alignment\n"); + retval = -EINVAL; + goto err_window; + } + + spin_lock(&image->lock); + + /* + * Let's allocate the resource here rather than further up the stack as + * it avoids pushing loads of bus dependent stuff up the stack + */ + retval = ca91cx42_alloc_resource(image, size); + if (retval) { + spin_unlock(&image->lock); + dev_err(ca91cx42_bridge->parent, "Unable to allocate memory " + "for resource name\n"); + retval = -ENOMEM; + goto err_res; + } + + pci_base = (unsigned long long)image->bus_resource.start; + + /* + * Bound address is a valid address for the window, adjust + * according to window granularity. + */ + pci_bound = pci_base + size; + vme_offset = vme_base - pci_base; + + /* Disable while we are mucking around */ + temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); + temp_ctl &= ~CA91CX42_LSI_CTL_EN; + iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); + + /* Setup cycle types */ + temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; + if (cycle & VME_BLT) + temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; + if (cycle & VME_MBLT) + temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; + + /* Setup data width */ + temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; + switch (dwidth) { + case VME_D8: + temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; + break; + case VME_D16: + temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; + break; + case VME_D32: + temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; + break; + case VME_D64: + temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; + break; + default: + spin_unlock(&image->lock); + dev_err(ca91cx42_bridge->parent, "Invalid data width\n"); + retval = -EINVAL; + goto err_dwidth; + break; + } + + /* Setup address space */ + temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; + switch (aspace) { + case VME_A16: + temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; + break; + case VME_A24: + temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; + break; + case VME_A32: + temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; + break; + case VME_CRCSR: + temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; + break; + case VME_USER1: + temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; + break; + case VME_USER2: + temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; + break; + case VME_A64: + case VME_USER3: + case VME_USER4: + default: + spin_unlock(&image->lock); + dev_err(ca91cx42_bridge->parent, "Invalid address space\n"); + retval = -EINVAL; + goto err_aspace; + break; + } + + temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); + if (cycle & VME_SUPER) + temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; + if (cycle & VME_PROG) + temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; + + /* Setup mapping */ + iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]); + iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]); + iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]); + + /* Write ctl reg without enable */ + iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); + + if (enabled) + temp_ctl |= CA91CX42_LSI_CTL_EN; + + iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]); + + spin_unlock(&image->lock); + return 0; + +err_aspace: +err_dwidth: + ca91cx42_free_resource(image); +err_res: +err_window: + return retval; +} + +static int __ca91cx42_master_get(struct vme_master_resource *image, + int *enabled, unsigned long long *vme_base, unsigned long long *size, + u32 *aspace, u32 *cycle, u32 *dwidth) +{ + unsigned int i, ctl; + unsigned long long pci_base, pci_bound, vme_offset; + struct ca91cx42_driver *bridge; + + bridge = image->parent->driver_priv; + + i = image->number; + + ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]); + + pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]); + vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]); + pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]); + + *vme_base = pci_base + vme_offset; + *size = (unsigned long long)(pci_bound - pci_base); + + *enabled = 0; + *aspace = 0; + *cycle = 0; + *dwidth = 0; + + if (ctl & CA91CX42_LSI_CTL_EN) + *enabled = 1; + + /* Setup address space */ + switch (ctl & CA91CX42_LSI_CTL_VAS_M) { + case CA91CX42_LSI_CTL_VAS_A16: + *aspace = VME_A16; + break; + case CA91CX42_LSI_CTL_VAS_A24: + *aspace = VME_A24; + break; + case CA91CX42_LSI_CTL_VAS_A32: + *aspace = VME_A32; + break; + case CA91CX42_LSI_CTL_VAS_CRCSR: + *aspace = VME_CRCSR; + break; + case CA91CX42_LSI_CTL_VAS_USER1: + *aspace = VME_USER1; + break; + case CA91CX42_LSI_CTL_VAS_USER2: + *aspace = VME_USER2; + break; + } + + /* XXX Not sure howto check for MBLT */ + /* Setup cycle types */ + if (ctl & CA91CX42_LSI_CTL_VCT_BLT) + *cycle |= VME_BLT; + else + *cycle |= VME_SCT; + + if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) + *cycle |= VME_SUPER; + else + *cycle |= VME_USER; + + if (ctl & CA91CX42_LSI_CTL_PGM_PGM) + *cycle = VME_PROG; + else + *cycle = VME_DATA; + + /* Setup data width */ + switch (ctl & CA91CX42_LSI_CTL_VDW_M) { + case CA91CX42_LSI_CTL_VDW_D8: + *dwidth = VME_D8; + break; + case CA91CX42_LSI_CTL_VDW_D16: + *dwidth = VME_D16; + break; + case CA91CX42_LSI_CTL_VDW_D32: + *dwidth = VME_D32; + break; + case CA91CX42_LSI_CTL_VDW_D64: + *dwidth = VME_D64; + break; + } + + return 0; +} + +static int ca91cx42_master_get(struct vme_master_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *dwidth) +{ + int retval; + + spin_lock(&image->lock); + + retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, + cycle, dwidth); + + spin_unlock(&image->lock); + + return retval; +} + +static ssize_t ca91cx42_master_read(struct vme_master_resource *image, + void *buf, size_t count, loff_t offset) +{ + ssize_t retval; + void *addr = image->kern_base + offset; + unsigned int done = 0; + unsigned int count32; + + if (count == 0) + return 0; + + spin_lock(&image->lock); + + /* The following code handles VME address alignment problem + * in order to assure the maximal data width cycle. + * We cannot use memcpy_xxx directly here because it + * may cut data transfer in 8-bits cycles, thus making + * D16 cycle impossible. + * From the other hand, the bridge itself assures that + * maximal configured data cycle is used and splits it + * automatically for non-aligned addresses. + */ + if ((uintptr_t)addr & 0x1) { + *(u8 *)buf = ioread8(addr); + done += 1; + if (done == count) + goto out; + } + if ((uintptr_t)addr & 0x2) { + if ((count - done) < 2) { + *(u8 *)(buf + done) = ioread8(addr + done); + done += 1; + goto out; + } else { + *(u16 *)(buf + done) = ioread16(addr + done); + done += 2; + } + } + + count32 = (count - done) & ~0x3; + if (count32 > 0) { + memcpy_fromio(buf + done, addr + done, (unsigned int)count); + done += count32; + } + + if ((count - done) & 0x2) { + *(u16 *)(buf + done) = ioread16(addr + done); + done += 2; + } + if ((count - done) & 0x1) { + *(u8 *)(buf + done) = ioread8(addr + done); + done += 1; + } +out: + retval = count; + spin_unlock(&image->lock); + + return retval; +} + +static ssize_t ca91cx42_master_write(struct vme_master_resource *image, + void *buf, size_t count, loff_t offset) +{ + ssize_t retval; + void *addr = image->kern_base + offset; + unsigned int done = 0; + unsigned int count32; + + if (count == 0) + return 0; + + spin_lock(&image->lock); + + /* Here we apply for the same strategy we do in master_read + * function in order to assure D16 cycle when required. + */ + if ((uintptr_t)addr & 0x1) { + iowrite8(*(u8 *)buf, addr); + done += 1; + if (done == count) + goto out; + } + if ((uintptr_t)addr & 0x2) { + if ((count - done) < 2) { + iowrite8(*(u8 *)(buf + done), addr + done); + done += 1; + goto out; + } else { + iowrite16(*(u16 *)(buf + done), addr + done); + done += 2; + } + } + + count32 = (count - done) & ~0x3; + if (count32 > 0) { + memcpy_toio(addr + done, buf + done, count32); + done += count32; + } + + if ((count - done) & 0x2) { + iowrite16(*(u16 *)(buf + done), addr + done); + done += 2; + } + if ((count - done) & 0x1) { + iowrite8(*(u8 *)(buf + done), addr + done); + done += 1; + } +out: + retval = count; + + spin_unlock(&image->lock); + + return retval; +} + +static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, + unsigned int mask, unsigned int compare, unsigned int swap, + loff_t offset) +{ + u32 result; + uintptr_t pci_addr; + int i; + struct ca91cx42_driver *bridge; + struct device *dev; + + bridge = image->parent->driver_priv; + dev = image->parent->parent; + + /* Find the PCI address that maps to the desired VME address */ + i = image->number; + + /* Locking as we can only do one of these at a time */ + mutex_lock(&bridge->vme_rmw); + + /* Lock image */ + spin_lock(&image->lock); + + pci_addr = (uintptr_t)image->kern_base + offset; + + /* Address must be 4-byte aligned */ + if (pci_addr & 0x3) { + dev_err(dev, "RMW Address not 4-byte aligned\n"); + result = -EINVAL; + goto out; + } + + /* Ensure RMW Disabled whilst configuring */ + iowrite32(0, bridge->base + SCYC_CTL); + + /* Configure registers */ + iowrite32(mask, bridge->base + SCYC_EN); + iowrite32(compare, bridge->base + SCYC_CMP); + iowrite32(swap, bridge->base + SCYC_SWP); + iowrite32(pci_addr, bridge->base + SCYC_ADDR); + + /* Enable RMW */ + iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL); + + /* Kick process off with a read to the required address. */ + result = ioread32(image->kern_base + offset); + + /* Disable RMW */ + iowrite32(0, bridge->base + SCYC_CTL); + +out: + spin_unlock(&image->lock); + + mutex_unlock(&bridge->vme_rmw); + + return result; +} + +static int ca91cx42_dma_list_add(struct vme_dma_list *list, + struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count) +{ + struct ca91cx42_dma_entry *entry, *prev; + struct vme_dma_pci *pci_attr; + struct vme_dma_vme *vme_attr; + dma_addr_t desc_ptr; + int retval = 0; + struct device *dev; + + dev = list->parent->parent->parent; + + /* XXX descriptor must be aligned on 64-bit boundaries */ + entry = kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL); + if (entry == NULL) { + dev_err(dev, "Failed to allocate memory for dma resource " + "structure\n"); + retval = -ENOMEM; + goto err_mem; + } + + /* Test descriptor alignment */ + if ((unsigned long)&entry->descriptor & CA91CX42_DCPP_M) { + dev_err(dev, "Descriptor not aligned to 16 byte boundary as " + "required: %p\n", &entry->descriptor); + retval = -EINVAL; + goto err_align; + } + + memset(&entry->descriptor, 0, sizeof(struct ca91cx42_dma_descriptor)); + + if (dest->type == VME_DMA_VME) { + entry->descriptor.dctl |= CA91CX42_DCTL_L2V; + vme_attr = dest->private; + pci_attr = src->private; + } else { + vme_attr = src->private; + pci_attr = dest->private; + } + + /* Check we can do fulfill required attributes */ + if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 | + VME_USER2)) != 0) { + + dev_err(dev, "Unsupported cycle type\n"); + retval = -EINVAL; + goto err_aspace; + } + + if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER | + VME_PROG | VME_DATA)) != 0) { + + dev_err(dev, "Unsupported cycle type\n"); + retval = -EINVAL; + goto err_cycle; + } + + /* Check to see if we can fulfill source and destination */ + if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) || + ((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) { + + dev_err(dev, "Cannot perform transfer with this " + "source-destination combination\n"); + retval = -EINVAL; + goto err_direct; + } + + /* Setup cycle types */ + if (vme_attr->cycle & VME_BLT) + entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT; + + /* Setup data width */ + switch (vme_attr->dwidth) { + case VME_D8: + entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8; + break; + case VME_D16: + entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16; + break; + case VME_D32: + entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32; + break; + case VME_D64: + entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64; + break; + default: + dev_err(dev, "Invalid data width\n"); + return -EINVAL; + } + + /* Setup address space */ + switch (vme_attr->aspace) { + case VME_A16: + entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16; + break; + case VME_A24: + entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24; + break; + case VME_A32: + entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32; + break; + case VME_USER1: + entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1; + break; + case VME_USER2: + entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2; + break; + default: + dev_err(dev, "Invalid address space\n"); + return -EINVAL; + break; + } + + if (vme_attr->cycle & VME_SUPER) + entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR; + if (vme_attr->cycle & VME_PROG) + entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM; + + entry->descriptor.dtbc = count; + entry->descriptor.dla = pci_attr->address; + entry->descriptor.dva = vme_attr->address; + entry->descriptor.dcpp = CA91CX42_DCPP_NULL; + + /* Add to list */ + list_add_tail(&entry->list, &list->entries); + + /* Fill out previous descriptors "Next Address" */ + if (entry->list.prev != &list->entries) { + prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry, + list); + /* We need the bus address for the pointer */ + desc_ptr = virt_to_bus(&entry->descriptor); + prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M; + } + + return 0; + +err_cycle: +err_aspace: +err_direct: +err_align: + kfree(entry); +err_mem: + return retval; +} + +static int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge) +{ + u32 tmp; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + tmp = ioread32(bridge->base + DGCS); + + if (tmp & CA91CX42_DGCS_ACT) + return 0; + else + return 1; +} + +static int ca91cx42_dma_list_exec(struct vme_dma_list *list) +{ + struct vme_dma_resource *ctrlr; + struct ca91cx42_dma_entry *entry; + int retval = 0; + dma_addr_t bus_addr; + u32 val; + struct device *dev; + struct ca91cx42_driver *bridge; + + ctrlr = list->parent; + + bridge = ctrlr->parent->driver_priv; + dev = ctrlr->parent->parent; + + mutex_lock(&ctrlr->mtx); + + if (!(list_empty(&ctrlr->running))) { + /* + * XXX We have an active DMA transfer and currently haven't + * sorted out the mechanism for "pending" DMA transfers. + * Return busy. + */ + /* Need to add to pending here */ + mutex_unlock(&ctrlr->mtx); + return -EBUSY; + } else { + list_add(&list->list, &ctrlr->running); + } + + /* Get first bus address and write into registers */ + entry = list_first_entry(&list->entries, struct ca91cx42_dma_entry, + list); + + bus_addr = virt_to_bus(&entry->descriptor); + + mutex_unlock(&ctrlr->mtx); + + iowrite32(0, bridge->base + DTBC); + iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP); + + /* Start the operation */ + val = ioread32(bridge->base + DGCS); + + /* XXX Could set VMEbus On and Off Counters here */ + val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M); + + val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT | + CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | + CA91CX42_DGCS_PERR); + + iowrite32(val, bridge->base + DGCS); + + val |= CA91CX42_DGCS_GO; + + iowrite32(val, bridge->base + DGCS); + + wait_event_interruptible(bridge->dma_queue, + ca91cx42_dma_busy(ctrlr->parent)); + + /* + * Read status register, this register is valid until we kick off a + * new transfer. + */ + val = ioread32(bridge->base + DGCS); + + if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR | + CA91CX42_DGCS_PERR)) { + + dev_err(dev, "ca91c042: DMA Error. DGCS=%08X\n", val); + val = ioread32(bridge->base + DCTL); + } + + /* Remove list from running list */ + mutex_lock(&ctrlr->mtx); + list_del(&list->list); + mutex_unlock(&ctrlr->mtx); + + return retval; + +} + +static int ca91cx42_dma_list_empty(struct vme_dma_list *list) +{ + struct list_head *pos, *temp; + struct ca91cx42_dma_entry *entry; + + /* detach and free each entry */ + list_for_each_safe(pos, temp, &list->entries) { + list_del(pos); + entry = list_entry(pos, struct ca91cx42_dma_entry, list); + kfree(entry); + } + + return 0; +} + +/* + * All 4 location monitors reside at the same base - this is therefore a + * system wide configuration. + * + * This does not enable the LM monitor - that should be done when the first + * callback is attached and disabled when the last callback is removed. + */ +static int ca91cx42_lm_set(struct vme_lm_resource *lm, + unsigned long long lm_base, u32 aspace, u32 cycle) +{ + u32 temp_base, lm_ctl = 0; + int i; + struct ca91cx42_driver *bridge; + struct device *dev; + + bridge = lm->parent->driver_priv; + dev = lm->parent->parent; + + /* Check the alignment of the location monitor */ + temp_base = (u32)lm_base; + if (temp_base & 0xffff) { + dev_err(dev, "Location monitor must be aligned to 64KB " + "boundary"); + return -EINVAL; + } + + mutex_lock(&lm->mtx); + + /* If we already have a callback attached, we can't move it! */ + for (i = 0; i < lm->monitors; i++) { + if (bridge->lm_callback[i] != NULL) { + mutex_unlock(&lm->mtx); + dev_err(dev, "Location monitor callback attached, " + "can't reset\n"); + return -EBUSY; + } + } + + switch (aspace) { + case VME_A16: + lm_ctl |= CA91CX42_LM_CTL_AS_A16; + break; + case VME_A24: + lm_ctl |= CA91CX42_LM_CTL_AS_A24; + break; + case VME_A32: + lm_ctl |= CA91CX42_LM_CTL_AS_A32; + break; + default: + mutex_unlock(&lm->mtx); + dev_err(dev, "Invalid address space\n"); + return -EINVAL; + break; + } + + if (cycle & VME_SUPER) + lm_ctl |= CA91CX42_LM_CTL_SUPR; + if (cycle & VME_USER) + lm_ctl |= CA91CX42_LM_CTL_NPRIV; + if (cycle & VME_PROG) + lm_ctl |= CA91CX42_LM_CTL_PGM; + if (cycle & VME_DATA) + lm_ctl |= CA91CX42_LM_CTL_DATA; + + iowrite32(lm_base, bridge->base + LM_BS); + iowrite32(lm_ctl, bridge->base + LM_CTL); + + mutex_unlock(&lm->mtx); + + return 0; +} + +/* Get configuration of the callback monitor and return whether it is enabled + * or disabled. + */ +static int ca91cx42_lm_get(struct vme_lm_resource *lm, + unsigned long long *lm_base, u32 *aspace, u32 *cycle) +{ + u32 lm_ctl, enabled = 0; + struct ca91cx42_driver *bridge; + + bridge = lm->parent->driver_priv; + + mutex_lock(&lm->mtx); + + *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); + lm_ctl = ioread32(bridge->base + LM_CTL); + + if (lm_ctl & CA91CX42_LM_CTL_EN) + enabled = 1; + + if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) + *aspace = VME_A16; + if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) + *aspace = VME_A24; + if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) + *aspace = VME_A32; + + *cycle = 0; + if (lm_ctl & CA91CX42_LM_CTL_SUPR) + *cycle |= VME_SUPER; + if (lm_ctl & CA91CX42_LM_CTL_NPRIV) + *cycle |= VME_USER; + if (lm_ctl & CA91CX42_LM_CTL_PGM) + *cycle |= VME_PROG; + if (lm_ctl & CA91CX42_LM_CTL_DATA) + *cycle |= VME_DATA; + + mutex_unlock(&lm->mtx); + + return enabled; +} + +/* + * Attach a callback to a specific location monitor. + * + * Callback will be passed the monitor triggered. + */ +static int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, + void (*callback)(int)) +{ + u32 lm_ctl, tmp; + struct ca91cx42_driver *bridge; + struct device *dev; + + bridge = lm->parent->driver_priv; + dev = lm->parent->parent; + + mutex_lock(&lm->mtx); + + /* Ensure that the location monitor is configured - need PGM or DATA */ + lm_ctl = ioread32(bridge->base + LM_CTL); + if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { + mutex_unlock(&lm->mtx); + dev_err(dev, "Location monitor not properly configured\n"); + return -EINVAL; + } + + /* Check that a callback isn't already attached */ + if (bridge->lm_callback[monitor] != NULL) { + mutex_unlock(&lm->mtx); + dev_err(dev, "Existing callback attached\n"); + return -EBUSY; + } + + /* Attach callback */ + bridge->lm_callback[monitor] = callback; + + /* Enable Location Monitor interrupt */ + tmp = ioread32(bridge->base + LINT_EN); + tmp |= CA91CX42_LINT_LM[monitor]; + iowrite32(tmp, bridge->base + LINT_EN); + + /* Ensure that global Location Monitor Enable set */ + if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { + lm_ctl |= CA91CX42_LM_CTL_EN; + iowrite32(lm_ctl, bridge->base + LM_CTL); + } + + mutex_unlock(&lm->mtx); + + return 0; +} + +/* + * Detach a callback function forn a specific location monitor. + */ +static int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) +{ + u32 tmp; + struct ca91cx42_driver *bridge; + + bridge = lm->parent->driver_priv; + + mutex_lock(&lm->mtx); + + /* Disable Location Monitor and ensure previous interrupts are clear */ + tmp = ioread32(bridge->base + LINT_EN); + tmp &= ~CA91CX42_LINT_LM[monitor]; + iowrite32(tmp, bridge->base + LINT_EN); + + iowrite32(CA91CX42_LINT_LM[monitor], + bridge->base + LINT_STAT); + + /* Detach callback */ + bridge->lm_callback[monitor] = NULL; + + /* If all location monitors disabled, disable global Location Monitor */ + if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | + CA91CX42_LINT_LM3)) == 0) { + tmp = ioread32(bridge->base + LM_CTL); + tmp &= ~CA91CX42_LM_CTL_EN; + iowrite32(tmp, bridge->base + LM_CTL); + } + + mutex_unlock(&lm->mtx); + + return 0; +} + +static int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) +{ + u32 slot = 0; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + if (!geoid) { + slot = ioread32(bridge->base + VCSR_BS); + slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); + } else + slot = geoid; + + return (int)slot; + +} + +void *ca91cx42_alloc_consistent(struct device *parent, size_t size, + dma_addr_t *dma) +{ + struct pci_dev *pdev; + + /* Find pci_dev container of dev */ + pdev = container_of(parent, struct pci_dev, dev); + + return pci_alloc_consistent(pdev, size, dma); +} + +void ca91cx42_free_consistent(struct device *parent, size_t size, void *vaddr, + dma_addr_t dma) +{ + struct pci_dev *pdev; + + /* Find pci_dev container of dev */ + pdev = container_of(parent, struct pci_dev, dev); + + pci_free_consistent(pdev, size, vaddr, dma); +} + +static int __init ca91cx42_init(void) +{ + return pci_register_driver(&ca91cx42_driver); +} + +/* + * Configure CR/CSR space + * + * Access to the CR/CSR can be configured at power-up. The location of the + * CR/CSR registers in the CR/CSR address space is determined by the boards + * Auto-ID or Geographic address. This function ensures that the window is + * enabled at an offset consistent with the boards geopgraphic address. + */ +static int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, + struct pci_dev *pdev) +{ + unsigned int crcsr_addr; + int tmp, slot; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + slot = ca91cx42_slot_get(ca91cx42_bridge); + + /* Write CSR Base Address if slot ID is supplied as a module param */ + if (geoid) + iowrite32(geoid << 27, bridge->base + VCSR_BS); + + dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); + if (slot == 0) { + dev_err(&pdev->dev, "Slot number is unset, not configuring " + "CR/CSR space\n"); + return -EINVAL; + } + + /* Allocate mem for CR/CSR image */ + bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, + &bridge->crcsr_bus); + if (bridge->crcsr_kernel == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " + "image\n"); + return -ENOMEM; + } + + memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); + + crcsr_addr = slot * (512 * 1024); + iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); + + tmp = ioread32(bridge->base + VCSR_CTL); + tmp |= CA91CX42_VCSR_CTL_EN; + iowrite32(tmp, bridge->base + VCSR_CTL); + + return 0; +} + +static void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge, + struct pci_dev *pdev) +{ + u32 tmp; + struct ca91cx42_driver *bridge; + + bridge = ca91cx42_bridge->driver_priv; + + /* Turn off CR/CSR space */ + tmp = ioread32(bridge->base + VCSR_CTL); + tmp &= ~CA91CX42_VCSR_CTL_EN; + iowrite32(tmp, bridge->base + VCSR_CTL); + + /* Free image */ + iowrite32(0, bridge->base + VCSR_TO); + + pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, + bridge->crcsr_bus); +} + +static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int retval, i; + u32 data; + struct list_head *pos = NULL; + struct vme_bridge *ca91cx42_bridge; + struct ca91cx42_driver *ca91cx42_device; + struct vme_master_resource *master_image; + struct vme_slave_resource *slave_image; + struct vme_dma_resource *dma_ctrlr; + struct vme_lm_resource *lm; + + /* We want to support more than one of each bridge so we need to + * dynamically allocate the bridge structure + */ + ca91cx42_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); + + if (ca91cx42_bridge == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for device " + "structure\n"); + retval = -ENOMEM; + goto err_struct; + } + + ca91cx42_device = kzalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL); + + if (ca91cx42_device == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for device " + "structure\n"); + retval = -ENOMEM; + goto err_driver; + } + + ca91cx42_bridge->driver_priv = ca91cx42_device; + + /* Enable the device */ + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "Unable to enable device\n"); + goto err_enable; + } + + /* Map Registers */ + retval = pci_request_regions(pdev, driver_name); + if (retval) { + dev_err(&pdev->dev, "Unable to reserve resources\n"); + goto err_resource; + } + + /* map registers in BAR 0 */ + ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0), + 4096); + if (!ca91cx42_device->base) { + dev_err(&pdev->dev, "Unable to remap CRG region\n"); + retval = -EIO; + goto err_remap; + } + + /* Check to see if the mapping worked out */ + data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF; + if (data != PCI_VENDOR_ID_TUNDRA) { + dev_err(&pdev->dev, "PCI_ID check failed\n"); + retval = -EIO; + goto err_test; + } + + /* Initialize wait queues & mutual exclusion flags */ + init_waitqueue_head(&ca91cx42_device->dma_queue); + init_waitqueue_head(&ca91cx42_device->iack_queue); + mutex_init(&ca91cx42_device->vme_int); + mutex_init(&ca91cx42_device->vme_rmw); + + ca91cx42_bridge->parent = &pdev->dev; + strcpy(ca91cx42_bridge->name, driver_name); + + /* Setup IRQ */ + retval = ca91cx42_irq_init(ca91cx42_bridge); + if (retval != 0) { + dev_err(&pdev->dev, "Chip Initialization failed.\n"); + goto err_irq; + } + + /* Add master windows to list */ + INIT_LIST_HEAD(&ca91cx42_bridge->master_resources); + for (i = 0; i < CA91C142_MAX_MASTER; i++) { + master_image = kmalloc(sizeof(struct vme_master_resource), + GFP_KERNEL); + if (master_image == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "master resource structure\n"); + retval = -ENOMEM; + goto err_master; + } + master_image->parent = ca91cx42_bridge; + spin_lock_init(&master_image->lock); + master_image->locked = 0; + master_image->number = i; + master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | + VME_CRCSR | VME_USER1 | VME_USER2; + master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | + VME_SUPER | VME_USER | VME_PROG | VME_DATA; + master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; + memset(&master_image->bus_resource, 0, + sizeof(struct resource)); + master_image->kern_base = NULL; + list_add_tail(&master_image->list, + &ca91cx42_bridge->master_resources); + } + + /* Add slave windows to list */ + INIT_LIST_HEAD(&ca91cx42_bridge->slave_resources); + for (i = 0; i < CA91C142_MAX_SLAVE; i++) { + slave_image = kmalloc(sizeof(struct vme_slave_resource), + GFP_KERNEL); + if (slave_image == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "slave resource structure\n"); + retval = -ENOMEM; + goto err_slave; + } + slave_image->parent = ca91cx42_bridge; + mutex_init(&slave_image->mtx); + slave_image->locked = 0; + slave_image->number = i; + slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | + VME_USER2; + + /* Only windows 0 and 4 support A16 */ + if (i == 0 || i == 4) + slave_image->address_attr |= VME_A16; + + slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | + VME_SUPER | VME_USER | VME_PROG | VME_DATA; + list_add_tail(&slave_image->list, + &ca91cx42_bridge->slave_resources); + } + + /* Add dma engines to list */ + INIT_LIST_HEAD(&ca91cx42_bridge->dma_resources); + for (i = 0; i < CA91C142_MAX_DMA; i++) { + dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), + GFP_KERNEL); + if (dma_ctrlr == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "dma resource structure\n"); + retval = -ENOMEM; + goto err_dma; + } + dma_ctrlr->parent = ca91cx42_bridge; + mutex_init(&dma_ctrlr->mtx); + dma_ctrlr->locked = 0; + dma_ctrlr->number = i; + dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | + VME_DMA_MEM_TO_VME; + INIT_LIST_HEAD(&dma_ctrlr->pending); + INIT_LIST_HEAD(&dma_ctrlr->running); + list_add_tail(&dma_ctrlr->list, + &ca91cx42_bridge->dma_resources); + } + + /* Add location monitor to list */ + INIT_LIST_HEAD(&ca91cx42_bridge->lm_resources); + lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); + if (lm == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "location monitor resource structure\n"); + retval = -ENOMEM; + goto err_lm; + } + lm->parent = ca91cx42_bridge; + mutex_init(&lm->mtx); + lm->locked = 0; + lm->number = 1; + lm->monitors = 4; + list_add_tail(&lm->list, &ca91cx42_bridge->lm_resources); + + ca91cx42_bridge->slave_get = ca91cx42_slave_get; + ca91cx42_bridge->slave_set = ca91cx42_slave_set; + ca91cx42_bridge->master_get = ca91cx42_master_get; + ca91cx42_bridge->master_set = ca91cx42_master_set; + ca91cx42_bridge->master_read = ca91cx42_master_read; + ca91cx42_bridge->master_write = ca91cx42_master_write; + ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; + ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; + ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; + ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; + ca91cx42_bridge->irq_set = ca91cx42_irq_set; + ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; + ca91cx42_bridge->lm_set = ca91cx42_lm_set; + ca91cx42_bridge->lm_get = ca91cx42_lm_get; + ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; + ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; + ca91cx42_bridge->slot_get = ca91cx42_slot_get; + ca91cx42_bridge->alloc_consistent = ca91cx42_alloc_consistent; + ca91cx42_bridge->free_consistent = ca91cx42_free_consistent; + + data = ioread32(ca91cx42_device->base + MISC_CTL); + dev_info(&pdev->dev, "Board is%s the VME system controller\n", + (data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); + dev_info(&pdev->dev, "Slot ID is %d\n", + ca91cx42_slot_get(ca91cx42_bridge)); + + if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) + dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); + + /* Need to save ca91cx42_bridge pointer locally in link list for use in + * ca91cx42_remove() + */ + retval = vme_register_bridge(ca91cx42_bridge); + if (retval != 0) { + dev_err(&pdev->dev, "Chip Registration failed.\n"); + goto err_reg; + } + + pci_set_drvdata(pdev, ca91cx42_bridge); + + return 0; + +err_reg: + ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); +err_lm: + /* resources are stored in link list */ + list_for_each(pos, &ca91cx42_bridge->lm_resources) { + lm = list_entry(pos, struct vme_lm_resource, list); + list_del(pos); + kfree(lm); + } +err_dma: + /* resources are stored in link list */ + list_for_each(pos, &ca91cx42_bridge->dma_resources) { + dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); + list_del(pos); + kfree(dma_ctrlr); + } +err_slave: + /* resources are stored in link list */ + list_for_each(pos, &ca91cx42_bridge->slave_resources) { + slave_image = list_entry(pos, struct vme_slave_resource, list); + list_del(pos); + kfree(slave_image); + } +err_master: + /* resources are stored in link list */ + list_for_each(pos, &ca91cx42_bridge->master_resources) { + master_image = list_entry(pos, struct vme_master_resource, + list); + list_del(pos); + kfree(master_image); + } + + ca91cx42_irq_exit(ca91cx42_device, pdev); +err_irq: +err_test: + iounmap(ca91cx42_device->base); +err_remap: + pci_release_regions(pdev); +err_resource: + pci_disable_device(pdev); +err_enable: + kfree(ca91cx42_device); +err_driver: + kfree(ca91cx42_bridge); +err_struct: + return retval; + +} + +static void ca91cx42_remove(struct pci_dev *pdev) +{ + struct list_head *pos = NULL; + struct vme_master_resource *master_image; + struct vme_slave_resource *slave_image; + struct vme_dma_resource *dma_ctrlr; + struct vme_lm_resource *lm; + struct ca91cx42_driver *bridge; + struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev); + + bridge = ca91cx42_bridge->driver_priv; + + + /* Turn off Ints */ + iowrite32(0, bridge->base + LINT_EN); + + /* Turn off the windows */ + iowrite32(0x00800000, bridge->base + LSI0_CTL); + iowrite32(0x00800000, bridge->base + LSI1_CTL); + iowrite32(0x00800000, bridge->base + LSI2_CTL); + iowrite32(0x00800000, bridge->base + LSI3_CTL); + iowrite32(0x00800000, bridge->base + LSI4_CTL); + iowrite32(0x00800000, bridge->base + LSI5_CTL); + iowrite32(0x00800000, bridge->base + LSI6_CTL); + iowrite32(0x00800000, bridge->base + LSI7_CTL); + iowrite32(0x00F00000, bridge->base + VSI0_CTL); + iowrite32(0x00F00000, bridge->base + VSI1_CTL); + iowrite32(0x00F00000, bridge->base + VSI2_CTL); + iowrite32(0x00F00000, bridge->base + VSI3_CTL); + iowrite32(0x00F00000, bridge->base + VSI4_CTL); + iowrite32(0x00F00000, bridge->base + VSI5_CTL); + iowrite32(0x00F00000, bridge->base + VSI6_CTL); + iowrite32(0x00F00000, bridge->base + VSI7_CTL); + + vme_unregister_bridge(ca91cx42_bridge); + + ca91cx42_crcsr_exit(ca91cx42_bridge, pdev); + + /* resources are stored in link list */ + list_for_each(pos, &ca91cx42_bridge->lm_resources) { + lm = list_entry(pos, struct vme_lm_resource, list); + list_del(pos); + kfree(lm); + } + + /* resources are stored in link list */ + list_for_each(pos, &ca91cx42_bridge->dma_resources) { + dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); + list_del(pos); + kfree(dma_ctrlr); + } + + /* resources are stored in link list */ + list_for_each(pos, &ca91cx42_bridge->slave_resources) { + slave_image = list_entry(pos, struct vme_slave_resource, list); + list_del(pos); + kfree(slave_image); + } + + /* resources are stored in link list */ + list_for_each(pos, &ca91cx42_bridge->master_resources) { + master_image = list_entry(pos, struct vme_master_resource, + list); + list_del(pos); + kfree(master_image); + } + + ca91cx42_irq_exit(bridge, pdev); + + iounmap(bridge->base); + + pci_release_regions(pdev); + + pci_disable_device(pdev); + + kfree(ca91cx42_bridge); +} + +static void __exit ca91cx42_exit(void) +{ + pci_unregister_driver(&ca91cx42_driver); +} + +MODULE_PARM_DESC(geoid, "Override geographical addressing"); +module_param(geoid, int, 0); + +MODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); +MODULE_LICENSE("GPL"); + +module_init(ca91cx42_init); +module_exit(ca91cx42_exit); diff --git a/drivers/vme/bridges/vme_ca91cx42.h b/drivers/vme/bridges/vme_ca91cx42.h new file mode 100644 index 000000000000..02a7c794db05 --- /dev/null +++ b/drivers/vme/bridges/vme_ca91cx42.h @@ -0,0 +1,583 @@ +/* + * ca91c042.h + * + * Support for the Tundra Universe 1 and Universe II VME bridge chips + * + * Author: Tom Armistead + * Updated by Ajit Prem + * Copyright 2004 Motorola Inc. + * + * Further updated by Martyn Welch + * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. + * + * Derived from ca91c042.h by Michael Wyrick + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _CA91CX42_H +#define _CA91CX42_H + +#ifndef PCI_VENDOR_ID_TUNDRA +#define PCI_VENDOR_ID_TUNDRA 0x10e3 +#endif + +#ifndef PCI_DEVICE_ID_TUNDRA_CA91C142 +#define PCI_DEVICE_ID_TUNDRA_CA91C142 0x0000 +#endif + +/* + * Define the number of each that the CA91C142 supports. + */ +#define CA91C142_MAX_MASTER 8 /* Max Master Windows */ +#define CA91C142_MAX_SLAVE 8 /* Max Slave Windows */ +#define CA91C142_MAX_DMA 1 /* Max DMA Controllers */ +#define CA91C142_MAX_MAILBOX 4 /* Max Mail Box registers */ + +/* Structure used to hold driver specific information */ +struct ca91cx42_driver { + void __iomem *base; /* Base Address of device registers */ + wait_queue_head_t dma_queue; + wait_queue_head_t iack_queue; + wait_queue_head_t mbox_queue; + void (*lm_callback[4])(int); /* Called in interrupt handler */ + void *crcsr_kernel; + dma_addr_t crcsr_bus; + struct mutex vme_rmw; /* Only one RMW cycle at a time */ + struct mutex vme_int; /* + * Only one VME interrupt can be + * generated at a time, provide locking + */ +}; + +/* See Page 2-77 in the Universe User Manual */ +struct ca91cx42_dma_descriptor { + unsigned int dctl; /* DMA Control */ + unsigned int dtbc; /* Transfer Byte Count */ + unsigned int dla; /* PCI Address */ + unsigned int res1; /* Reserved */ + unsigned int dva; /* Vme Address */ + unsigned int res2; /* Reserved */ + unsigned int dcpp; /* Pointer to Numed Cmd Packet with rPN */ + unsigned int res3; /* Reserved */ +}; + +struct ca91cx42_dma_entry { + struct ca91cx42_dma_descriptor descriptor; + struct list_head list; +}; + +/* Universe Register Offsets */ +/* general PCI configuration registers */ +#define CA91CX42_PCI_ID 0x000 +#define CA91CX42_PCI_CSR 0x004 +#define CA91CX42_PCI_CLASS 0x008 +#define CA91CX42_PCI_MISC0 0x00C +#define CA91CX42_PCI_BS 0x010 +#define CA91CX42_PCI_MISC1 0x03C + +#define LSI0_CTL 0x0100 +#define LSI0_BS 0x0104 +#define LSI0_BD 0x0108 +#define LSI0_TO 0x010C + +#define LSI1_CTL 0x0114 +#define LSI1_BS 0x0118 +#define LSI1_BD 0x011C +#define LSI1_TO 0x0120 + +#define LSI2_CTL 0x0128 +#define LSI2_BS 0x012C +#define LSI2_BD 0x0130 +#define LSI2_TO 0x0134 + +#define LSI3_CTL 0x013C +#define LSI3_BS 0x0140 +#define LSI3_BD 0x0144 +#define LSI3_TO 0x0148 + +#define LSI4_CTL 0x01A0 +#define LSI4_BS 0x01A4 +#define LSI4_BD 0x01A8 +#define LSI4_TO 0x01AC + +#define LSI5_CTL 0x01B4 +#define LSI5_BS 0x01B8 +#define LSI5_BD 0x01BC +#define LSI5_TO 0x01C0 + +#define LSI6_CTL 0x01C8 +#define LSI6_BS 0x01CC +#define LSI6_BD 0x01D0 +#define LSI6_TO 0x01D4 + +#define LSI7_CTL 0x01DC +#define LSI7_BS 0x01E0 +#define LSI7_BD 0x01E4 +#define LSI7_TO 0x01E8 + +static const int CA91CX42_LSI_CTL[] = { LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL, + LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL }; + +static const int CA91CX42_LSI_BS[] = { LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS, + LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS }; + +static const int CA91CX42_LSI_BD[] = { LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD, + LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD }; + +static const int CA91CX42_LSI_TO[] = { LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO, + LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO }; + +#define SCYC_CTL 0x0170 +#define SCYC_ADDR 0x0174 +#define SCYC_EN 0x0178 +#define SCYC_CMP 0x017C +#define SCYC_SWP 0x0180 +#define LMISC 0x0184 +#define SLSI 0x0188 +#define L_CMDERR 0x018C +#define LAERR 0x0190 + +#define DCTL 0x0200 +#define DTBC 0x0204 +#define DLA 0x0208 +#define DVA 0x0210 +#define DCPP 0x0218 +#define DGCS 0x0220 +#define D_LLUE 0x0224 + +#define LINT_EN 0x0300 +#define LINT_STAT 0x0304 +#define LINT_MAP0 0x0308 +#define LINT_MAP1 0x030C +#define VINT_EN 0x0310 +#define VINT_STAT 0x0314 +#define VINT_MAP0 0x0318 +#define VINT_MAP1 0x031C +#define STATID 0x0320 + +#define V1_STATID 0x0324 +#define V2_STATID 0x0328 +#define V3_STATID 0x032C +#define V4_STATID 0x0330 +#define V5_STATID 0x0334 +#define V6_STATID 0x0338 +#define V7_STATID 0x033C + +static const int CA91CX42_V_STATID[8] = { 0, V1_STATID, V2_STATID, V3_STATID, + V4_STATID, V5_STATID, V6_STATID, + V7_STATID }; + +#define LINT_MAP2 0x0340 +#define VINT_MAP2 0x0344 + +#define MBOX0 0x0348 +#define MBOX1 0x034C +#define MBOX2 0x0350 +#define MBOX3 0x0354 +#define SEMA0 0x0358 +#define SEMA1 0x035C + +#define MAST_CTL 0x0400 +#define MISC_CTL 0x0404 +#define MISC_STAT 0x0408 +#define USER_AM 0x040C + +#define VSI0_CTL 0x0F00 +#define VSI0_BS 0x0F04 +#define VSI0_BD 0x0F08 +#define VSI0_TO 0x0F0C + +#define VSI1_CTL 0x0F14 +#define VSI1_BS 0x0F18 +#define VSI1_BD 0x0F1C +#define VSI1_TO 0x0F20 + +#define VSI2_CTL 0x0F28 +#define VSI2_BS 0x0F2C +#define VSI2_BD 0x0F30 +#define VSI2_TO 0x0F34 + +#define VSI3_CTL 0x0F3C +#define VSI3_BS 0x0F40 +#define VSI3_BD 0x0F44 +#define VSI3_TO 0x0F48 + +#define LM_CTL 0x0F64 +#define LM_BS 0x0F68 + +#define VRAI_CTL 0x0F70 + +#define VRAI_BS 0x0F74 +#define VCSR_CTL 0x0F80 +#define VCSR_TO 0x0F84 +#define V_AMERR 0x0F88 +#define VAERR 0x0F8C + +#define VSI4_CTL 0x0F90 +#define VSI4_BS 0x0F94 +#define VSI4_BD 0x0F98 +#define VSI4_TO 0x0F9C + +#define VSI5_CTL 0x0FA4 +#define VSI5_BS 0x0FA8 +#define VSI5_BD 0x0FAC +#define VSI5_TO 0x0FB0 + +#define VSI6_CTL 0x0FB8 +#define VSI6_BS 0x0FBC +#define VSI6_BD 0x0FC0 +#define VSI6_TO 0x0FC4 + +#define VSI7_CTL 0x0FCC +#define VSI7_BS 0x0FD0 +#define VSI7_BD 0x0FD4 +#define VSI7_TO 0x0FD8 + +static const int CA91CX42_VSI_CTL[] = { VSI0_CTL, VSI1_CTL, VSI2_CTL, VSI3_CTL, + VSI4_CTL, VSI5_CTL, VSI6_CTL, VSI7_CTL }; + +static const int CA91CX42_VSI_BS[] = { VSI0_BS, VSI1_BS, VSI2_BS, VSI3_BS, + VSI4_BS, VSI5_BS, VSI6_BS, VSI7_BS }; + +static const int CA91CX42_VSI_BD[] = { VSI0_BD, VSI1_BD, VSI2_BD, VSI3_BD, + VSI4_BD, VSI5_BD, VSI6_BD, VSI7_BD }; + +static const int CA91CX42_VSI_TO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO, + VSI4_TO, VSI5_TO, VSI6_TO, VSI7_TO }; + +#define VCSR_CLR 0x0FF4 +#define VCSR_SET 0x0FF8 +#define VCSR_BS 0x0FFC + +/* + * PCI Class Register + * offset 008 + */ +#define CA91CX42_BM_PCI_CLASS_BASE 0xFF000000 +#define CA91CX42_OF_PCI_CLASS_BASE 24 +#define CA91CX42_BM_PCI_CLASS_SUB 0x00FF0000 +#define CA91CX42_OF_PCI_CLASS_SUB 16 +#define CA91CX42_BM_PCI_CLASS_PROG 0x0000FF00 +#define CA91CX42_OF_PCI_CLASS_PROG 8 +#define CA91CX42_BM_PCI_CLASS_RID 0x000000FF +#define CA91CX42_OF_PCI_CLASS_RID 0 + +#define CA91CX42_OF_PCI_CLASS_RID_UNIVERSE_I 0 +#define CA91CX42_OF_PCI_CLASS_RID_UNIVERSE_II 1 + +/* + * PCI Misc Register + * offset 00C + */ +#define CA91CX42_BM_PCI_MISC0_BISTC 0x80000000 +#define CA91CX42_BM_PCI_MISC0_SBIST 0x60000000 +#define CA91CX42_BM_PCI_MISC0_CCODE 0x0F000000 +#define CA91CX42_BM_PCI_MISC0_MFUNCT 0x00800000 +#define CA91CX42_BM_PCI_MISC0_LAYOUT 0x007F0000 +#define CA91CX42_BM_PCI_MISC0_LTIMER 0x0000FF00 +#define CA91CX42_OF_PCI_MISC0_LTIMER 8 + + +/* + * LSI Control Register + * offset 100 + */ +#define CA91CX42_LSI_CTL_EN (1<<31) +#define CA91CX42_LSI_CTL_PWEN (1<<30) + +#define CA91CX42_LSI_CTL_VDW_M (3<<22) +#define CA91CX42_LSI_CTL_VDW_D8 0 +#define CA91CX42_LSI_CTL_VDW_D16 (1<<22) +#define CA91CX42_LSI_CTL_VDW_D32 (1<<23) +#define CA91CX42_LSI_CTL_VDW_D64 (3<<22) + +#define CA91CX42_LSI_CTL_VAS_M (7<<16) +#define CA91CX42_LSI_CTL_VAS_A16 0 +#define CA91CX42_LSI_CTL_VAS_A24 (1<<16) +#define CA91CX42_LSI_CTL_VAS_A32 (1<<17) +#define CA91CX42_LSI_CTL_VAS_CRCSR (5<<16) +#define CA91CX42_LSI_CTL_VAS_USER1 (3<<17) +#define CA91CX42_LSI_CTL_VAS_USER2 (7<<16) + +#define CA91CX42_LSI_CTL_PGM_M (1<<14) +#define CA91CX42_LSI_CTL_PGM_DATA 0 +#define CA91CX42_LSI_CTL_PGM_PGM (1<<14) + +#define CA91CX42_LSI_CTL_SUPER_M (1<<12) +#define CA91CX42_LSI_CTL_SUPER_NPRIV 0 +#define CA91CX42_LSI_CTL_SUPER_SUPR (1<<12) + +#define CA91CX42_LSI_CTL_VCT_M (1<<8) +#define CA91CX42_LSI_CTL_VCT_BLT (1<<8) +#define CA91CX42_LSI_CTL_VCT_MBLT (1<<8) +#define CA91CX42_LSI_CTL_LAS (1<<0) + +/* + * SCYC_CTL Register + * offset 178 + */ +#define CA91CX42_SCYC_CTL_LAS_PCIMEM 0 +#define CA91CX42_SCYC_CTL_LAS_PCIIO (1<<2) + +#define CA91CX42_SCYC_CTL_CYC_M (3<<0) +#define CA91CX42_SCYC_CTL_CYC_RMW (1<<0) +#define CA91CX42_SCYC_CTL_CYC_ADOH (1<<1) + +/* + * LMISC Register + * offset 184 + */ +#define CA91CX42_BM_LMISC_CRT 0xF0000000 +#define CA91CX42_OF_LMISC_CRT 28 +#define CA91CX42_BM_LMISC_CWT 0x0F000000 +#define CA91CX42_OF_LMISC_CWT 24 + +/* + * SLSI Register + * offset 188 + */ +#define CA91CX42_BM_SLSI_EN 0x80000000 +#define CA91CX42_BM_SLSI_PWEN 0x40000000 +#define CA91CX42_BM_SLSI_VDW 0x00F00000 +#define CA91CX42_OF_SLSI_VDW 20 +#define CA91CX42_BM_SLSI_PGM 0x0000F000 +#define CA91CX42_OF_SLSI_PGM 12 +#define CA91CX42_BM_SLSI_SUPER 0x00000F00 +#define CA91CX42_OF_SLSI_SUPER 8 +#define CA91CX42_BM_SLSI_BS 0x000000F6 +#define CA91CX42_OF_SLSI_BS 2 +#define CA91CX42_BM_SLSI_LAS 0x00000003 +#define CA91CX42_OF_SLSI_LAS 0 +#define CA91CX42_BM_SLSI_RESERVED 0x3F0F0000 + +/* + * DCTL Register + * offset 200 + */ +#define CA91CX42_DCTL_L2V (1<<31) +#define CA91CX42_DCTL_VDW_M (3<<22) +#define CA91CX42_DCTL_VDW_M (3<<22) +#define CA91CX42_DCTL_VDW_D8 0 +#define CA91CX42_DCTL_VDW_D16 (1<<22) +#define CA91CX42_DCTL_VDW_D32 (1<<23) +#define CA91CX42_DCTL_VDW_D64 (3<<22) + +#define CA91CX42_DCTL_VAS_M (7<<16) +#define CA91CX42_DCTL_VAS_A16 0 +#define CA91CX42_DCTL_VAS_A24 (1<<16) +#define CA91CX42_DCTL_VAS_A32 (1<<17) +#define CA91CX42_DCTL_VAS_USER1 (3<<17) +#define CA91CX42_DCTL_VAS_USER2 (7<<16) + +#define CA91CX42_DCTL_PGM_M (1<<14) +#define CA91CX42_DCTL_PGM_DATA 0 +#define CA91CX42_DCTL_PGM_PGM (1<<14) + +#define CA91CX42_DCTL_SUPER_M (1<<12) +#define CA91CX42_DCTL_SUPER_NPRIV 0 +#define CA91CX42_DCTL_SUPER_SUPR (1<<12) + +#define CA91CX42_DCTL_VCT_M (1<<8) +#define CA91CX42_DCTL_VCT_BLT (1<<8) +#define CA91CX42_DCTL_LD64EN (1<<7) + +/* + * DCPP Register + * offset 218 + */ +#define CA91CX42_DCPP_M 0xf +#define CA91CX42_DCPP_NULL (1<<0) + +/* + * DMA General Control/Status Register (DGCS) + * offset 220 + */ +#define CA91CX42_DGCS_GO (1<<31) +#define CA91CX42_DGCS_STOP_REQ (1<<30) +#define CA91CX42_DGCS_HALT_REQ (1<<29) +#define CA91CX42_DGCS_CHAIN (1<<27) + +#define CA91CX42_DGCS_VON_M (7<<20) + +#define CA91CX42_DGCS_VOFF_M (0xf<<16) + +#define CA91CX42_DGCS_ACT (1<<15) +#define CA91CX42_DGCS_STOP (1<<14) +#define CA91CX42_DGCS_HALT (1<<13) +#define CA91CX42_DGCS_DONE (1<<11) +#define CA91CX42_DGCS_LERR (1<<10) +#define CA91CX42_DGCS_VERR (1<<9) +#define CA91CX42_DGCS_PERR (1<<8) +#define CA91CX42_DGCS_INT_STOP (1<<6) +#define CA91CX42_DGCS_INT_HALT (1<<5) +#define CA91CX42_DGCS_INT_DONE (1<<3) +#define CA91CX42_DGCS_INT_LERR (1<<2) +#define CA91CX42_DGCS_INT_VERR (1<<1) +#define CA91CX42_DGCS_INT_PERR (1<<0) + +/* + * PCI Interrupt Enable Register + * offset 300 + */ +#define CA91CX42_LINT_LM3 0x00800000 +#define CA91CX42_LINT_LM2 0x00400000 +#define CA91CX42_LINT_LM1 0x00200000 +#define CA91CX42_LINT_LM0 0x00100000 +#define CA91CX42_LINT_MBOX3 0x00080000 +#define CA91CX42_LINT_MBOX2 0x00040000 +#define CA91CX42_LINT_MBOX1 0x00020000 +#define CA91CX42_LINT_MBOX0 0x00010000 +#define CA91CX42_LINT_ACFAIL 0x00008000 +#define CA91CX42_LINT_SYSFAIL 0x00004000 +#define CA91CX42_LINT_SW_INT 0x00002000 +#define CA91CX42_LINT_SW_IACK 0x00001000 + +#define CA91CX42_LINT_VERR 0x00000400 +#define CA91CX42_LINT_LERR 0x00000200 +#define CA91CX42_LINT_DMA 0x00000100 +#define CA91CX42_LINT_VIRQ7 0x00000080 +#define CA91CX42_LINT_VIRQ6 0x00000040 +#define CA91CX42_LINT_VIRQ5 0x00000020 +#define CA91CX42_LINT_VIRQ4 0x00000010 +#define CA91CX42_LINT_VIRQ3 0x00000008 +#define CA91CX42_LINT_VIRQ2 0x00000004 +#define CA91CX42_LINT_VIRQ1 0x00000002 +#define CA91CX42_LINT_VOWN 0x00000001 + +static const int CA91CX42_LINT_VIRQ[] = { 0, CA91CX42_LINT_VIRQ1, + CA91CX42_LINT_VIRQ2, CA91CX42_LINT_VIRQ3, + CA91CX42_LINT_VIRQ4, CA91CX42_LINT_VIRQ5, + CA91CX42_LINT_VIRQ6, CA91CX42_LINT_VIRQ7 }; + +#define CA91CX42_LINT_MBOX 0x000F0000 + +static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1, + CA91CX42_LINT_LM2, CA91CX42_LINT_LM3 }; + +/* + * MAST_CTL Register + * offset 400 + */ +#define CA91CX42_BM_MAST_CTL_MAXRTRY 0xF0000000 +#define CA91CX42_OF_MAST_CTL_MAXRTRY 28 +#define CA91CX42_BM_MAST_CTL_PWON 0x0F000000 +#define CA91CX42_OF_MAST_CTL_PWON 24 +#define CA91CX42_BM_MAST_CTL_VRL 0x00C00000 +#define CA91CX42_OF_MAST_CTL_VRL 22 +#define CA91CX42_BM_MAST_CTL_VRM 0x00200000 +#define CA91CX42_BM_MAST_CTL_VREL 0x00100000 +#define CA91CX42_BM_MAST_CTL_VOWN 0x00080000 +#define CA91CX42_BM_MAST_CTL_VOWN_ACK 0x00040000 +#define CA91CX42_BM_MAST_CTL_PABS 0x00001000 +#define CA91CX42_BM_MAST_CTL_BUS_NO 0x0000000F +#define CA91CX42_OF_MAST_CTL_BUS_NO 0 + +/* + * MISC_CTL Register + * offset 404 + */ +#define CA91CX42_MISC_CTL_VBTO 0xF0000000 +#define CA91CX42_MISC_CTL_VARB 0x04000000 +#define CA91CX42_MISC_CTL_VARBTO 0x03000000 +#define CA91CX42_MISC_CTL_SW_LRST 0x00800000 +#define CA91CX42_MISC_CTL_SW_SRST 0x00400000 +#define CA91CX42_MISC_CTL_BI 0x00100000 +#define CA91CX42_MISC_CTL_ENGBI 0x00080000 +#define CA91CX42_MISC_CTL_RESCIND 0x00040000 +#define CA91CX42_MISC_CTL_SYSCON 0x00020000 +#define CA91CX42_MISC_CTL_V64AUTO 0x00010000 +#define CA91CX42_MISC_CTL_RESERVED 0x0820FFFF + +#define CA91CX42_OF_MISC_CTL_VARBTO 24 +#define CA91CX42_OF_MISC_CTL_VBTO 28 + +/* + * MISC_STAT Register + * offset 408 + */ +#define CA91CX42_BM_MISC_STAT_ENDIAN 0x80000000 +#define CA91CX42_BM_MISC_STAT_LCLSIZE 0x40000000 +#define CA91CX42_BM_MISC_STAT_DY4AUTO 0x08000000 +#define CA91CX42_BM_MISC_STAT_MYBBSY 0x00200000 +#define CA91CX42_BM_MISC_STAT_DY4DONE 0x00080000 +#define CA91CX42_BM_MISC_STAT_TXFE 0x00040000 +#define CA91CX42_BM_MISC_STAT_RXFE 0x00020000 +#define CA91CX42_BM_MISC_STAT_DY4AUTOID 0x0000FF00 +#define CA91CX42_OF_MISC_STAT_DY4AUTOID 8 + +/* + * VSI Control Register + * offset F00 + */ +#define CA91CX42_VSI_CTL_EN (1<<31) +#define CA91CX42_VSI_CTL_PWEN (1<<30) +#define CA91CX42_VSI_CTL_PREN (1<<29) + +#define CA91CX42_VSI_CTL_PGM_M (3<<22) +#define CA91CX42_VSI_CTL_PGM_DATA (1<<22) +#define CA91CX42_VSI_CTL_PGM_PGM (1<<23) + +#define CA91CX42_VSI_CTL_SUPER_M (3<<20) +#define CA91CX42_VSI_CTL_SUPER_NPRIV (1<<20) +#define CA91CX42_VSI_CTL_SUPER_SUPR (1<<21) + +#define CA91CX42_VSI_CTL_VAS_M (7<<16) +#define CA91CX42_VSI_CTL_VAS_A16 0 +#define CA91CX42_VSI_CTL_VAS_A24 (1<<16) +#define CA91CX42_VSI_CTL_VAS_A32 (1<<17) +#define CA91CX42_VSI_CTL_VAS_USER1 (3<<17) +#define CA91CX42_VSI_CTL_VAS_USER2 (7<<16) + +#define CA91CX42_VSI_CTL_LD64EN (1<<7) +#define CA91CX42_VSI_CTL_LLRMW (1<<6) + +#define CA91CX42_VSI_CTL_LAS_M (3<<0) +#define CA91CX42_VSI_CTL_LAS_PCI_MS 0 +#define CA91CX42_VSI_CTL_LAS_PCI_IO (1<<0) +#define CA91CX42_VSI_CTL_LAS_PCI_CONF (1<<1) + +/* LM_CTL Register + * offset F64 + */ +#define CA91CX42_LM_CTL_EN (1<<31) +#define CA91CX42_LM_CTL_PGM (1<<23) +#define CA91CX42_LM_CTL_DATA (1<<22) +#define CA91CX42_LM_CTL_SUPR (1<<21) +#define CA91CX42_LM_CTL_NPRIV (1<<20) +#define CA91CX42_LM_CTL_AS_M (5<<16) +#define CA91CX42_LM_CTL_AS_A16 0 +#define CA91CX42_LM_CTL_AS_A24 (1<<16) +#define CA91CX42_LM_CTL_AS_A32 (1<<17) + +/* + * VRAI_CTL Register + * offset F70 + */ +#define CA91CX42_BM_VRAI_CTL_EN 0x80000000 +#define CA91CX42_BM_VRAI_CTL_PGM 0x00C00000 +#define CA91CX42_OF_VRAI_CTL_PGM 22 +#define CA91CX42_BM_VRAI_CTL_SUPER 0x00300000 +#define CA91CX42_OF_VRAI_CTL_SUPER 20 +#define CA91CX42_BM_VRAI_CTL_VAS 0x00030000 +#define CA91CX42_OF_VRAI_CTL_VAS 16 + +/* VCSR_CTL Register + * offset F80 + */ +#define CA91CX42_VCSR_CTL_EN (1<<31) + +#define CA91CX42_VCSR_CTL_LAS_M (3<<0) +#define CA91CX42_VCSR_CTL_LAS_PCI_MS 0 +#define CA91CX42_VCSR_CTL_LAS_PCI_IO (1<<0) +#define CA91CX42_VCSR_CTL_LAS_PCI_CONF (1<<1) + +/* VCSR_BS Register + * offset FFC + */ +#define CA91CX42_VCSR_BS_SLOT_M (0x1F<<27) + +#endif /* _CA91CX42_H */ diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c new file mode 100644 index 000000000000..081e9c4c5e71 --- /dev/null +++ b/drivers/vme/bridges/vme_tsi148.c @@ -0,0 +1,2691 @@ +/* + * Support for the Tundra TSI148 VME-PCI Bridge Chip + * + * Author: Martyn Welch + * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. + * + * Based on work by Tom Armistead and Ajit Prem + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../vme_bridge.h" +#include "vme_tsi148.h" + +static int __init tsi148_init(void); +static int tsi148_probe(struct pci_dev *, const struct pci_device_id *); +static void tsi148_remove(struct pci_dev *); +static void __exit tsi148_exit(void); + + +/* Module parameter */ +static bool err_chk; +static int geoid; + +static const char driver_name[] = "vme_tsi148"; + +static DEFINE_PCI_DEVICE_TABLE(tsi148_ids) = { + { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) }, + { }, +}; + +static struct pci_driver tsi148_driver = { + .name = driver_name, + .id_table = tsi148_ids, + .probe = tsi148_probe, + .remove = tsi148_remove, +}; + +static void reg_join(unsigned int high, unsigned int low, + unsigned long long *variable) +{ + *variable = (unsigned long long)high << 32; + *variable |= (unsigned long long)low; +} + +static void reg_split(unsigned long long variable, unsigned int *high, + unsigned int *low) +{ + *low = (unsigned int)variable & 0xFFFFFFFF; + *high = (unsigned int)(variable >> 32); +} + +/* + * Wakes up DMA queue. + */ +static u32 tsi148_DMA_irqhandler(struct tsi148_driver *bridge, + int channel_mask) +{ + u32 serviced = 0; + + if (channel_mask & TSI148_LCSR_INTS_DMA0S) { + wake_up(&bridge->dma_queue[0]); + serviced |= TSI148_LCSR_INTC_DMA0C; + } + if (channel_mask & TSI148_LCSR_INTS_DMA1S) { + wake_up(&bridge->dma_queue[1]); + serviced |= TSI148_LCSR_INTC_DMA1C; + } + + return serviced; +} + +/* + * Wake up location monitor queue + */ +static u32 tsi148_LM_irqhandler(struct tsi148_driver *bridge, u32 stat) +{ + int i; + u32 serviced = 0; + + for (i = 0; i < 4; i++) { + if (stat & TSI148_LCSR_INTS_LMS[i]) { + /* We only enable interrupts if the callback is set */ + bridge->lm_callback[i](i); + serviced |= TSI148_LCSR_INTC_LMC[i]; + } + } + + return serviced; +} + +/* + * Wake up mail box queue. + * + * XXX This functionality is not exposed up though API. + */ +static u32 tsi148_MB_irqhandler(struct vme_bridge *tsi148_bridge, u32 stat) +{ + int i; + u32 val; + u32 serviced = 0; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + for (i = 0; i < 4; i++) { + if (stat & TSI148_LCSR_INTS_MBS[i]) { + val = ioread32be(bridge->base + TSI148_GCSR_MBOX[i]); + dev_err(tsi148_bridge->parent, "VME Mailbox %d received" + ": 0x%x\n", i, val); + serviced |= TSI148_LCSR_INTC_MBC[i]; + } + } + + return serviced; +} + +/* + * Display error & status message when PERR (PCI) exception interrupt occurs. + */ +static u32 tsi148_PERR_irqhandler(struct vme_bridge *tsi148_bridge) +{ + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + dev_err(tsi148_bridge->parent, "PCI Exception at address: 0x%08x:%08x, " + "attributes: %08x\n", + ioread32be(bridge->base + TSI148_LCSR_EDPAU), + ioread32be(bridge->base + TSI148_LCSR_EDPAL), + ioread32be(bridge->base + TSI148_LCSR_EDPAT)); + + dev_err(tsi148_bridge->parent, "PCI-X attribute reg: %08x, PCI-X split " + "completion reg: %08x\n", + ioread32be(bridge->base + TSI148_LCSR_EDPXA), + ioread32be(bridge->base + TSI148_LCSR_EDPXS)); + + iowrite32be(TSI148_LCSR_EDPAT_EDPCL, bridge->base + TSI148_LCSR_EDPAT); + + return TSI148_LCSR_INTC_PERRC; +} + +/* + * Save address and status when VME error interrupt occurs. + */ +static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge) +{ + unsigned int error_addr_high, error_addr_low; + unsigned long long error_addr; + u32 error_attrib; + struct vme_bus_error *error; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU); + error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL); + error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT); + + reg_join(error_addr_high, error_addr_low, &error_addr); + + /* Check for exception register overflow (we have lost error data) */ + if (error_attrib & TSI148_LCSR_VEAT_VEOF) { + dev_err(tsi148_bridge->parent, "VME Bus Exception Overflow " + "Occurred\n"); + } + + error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC); + if (error) { + error->address = error_addr; + error->attributes = error_attrib; + list_add_tail(&error->list, &tsi148_bridge->vme_errors); + } else { + dev_err(tsi148_bridge->parent, "Unable to alloc memory for " + "VMEbus Error reporting\n"); + dev_err(tsi148_bridge->parent, "VME Bus Error at address: " + "0x%llx, attributes: %08x\n", error_addr, error_attrib); + } + + /* Clear Status */ + iowrite32be(TSI148_LCSR_VEAT_VESCL, bridge->base + TSI148_LCSR_VEAT); + + return TSI148_LCSR_INTC_VERRC; +} + +/* + * Wake up IACK queue. + */ +static u32 tsi148_IACK_irqhandler(struct tsi148_driver *bridge) +{ + wake_up(&bridge->iack_queue); + + return TSI148_LCSR_INTC_IACKC; +} + +/* + * Calling VME bus interrupt callback if provided. + */ +static u32 tsi148_VIRQ_irqhandler(struct vme_bridge *tsi148_bridge, + u32 stat) +{ + int vec, i, serviced = 0; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + for (i = 7; i > 0; i--) { + if (stat & (1 << i)) { + /* + * Note: Even though the registers are defined as + * 32-bits in the spec, we only want to issue 8-bit + * IACK cycles on the bus, read from offset 3. + */ + vec = ioread8(bridge->base + TSI148_LCSR_VIACK[i] + 3); + + vme_irq_handler(tsi148_bridge, i, vec); + + serviced |= (1 << i); + } + } + + return serviced; +} + +/* + * Top level interrupt handler. Clears appropriate interrupt status bits and + * then calls appropriate sub handler(s). + */ +static irqreturn_t tsi148_irqhandler(int irq, void *ptr) +{ + u32 stat, enable, serviced = 0; + struct vme_bridge *tsi148_bridge; + struct tsi148_driver *bridge; + + tsi148_bridge = ptr; + + bridge = tsi148_bridge->driver_priv; + + /* Determine which interrupts are unmasked and set */ + enable = ioread32be(bridge->base + TSI148_LCSR_INTEO); + stat = ioread32be(bridge->base + TSI148_LCSR_INTS); + + /* Only look at unmasked interrupts */ + stat &= enable; + + if (unlikely(!stat)) + return IRQ_NONE; + + /* Call subhandlers as appropriate */ + /* DMA irqs */ + if (stat & (TSI148_LCSR_INTS_DMA1S | TSI148_LCSR_INTS_DMA0S)) + serviced |= tsi148_DMA_irqhandler(bridge, stat); + + /* Location monitor irqs */ + if (stat & (TSI148_LCSR_INTS_LM3S | TSI148_LCSR_INTS_LM2S | + TSI148_LCSR_INTS_LM1S | TSI148_LCSR_INTS_LM0S)) + serviced |= tsi148_LM_irqhandler(bridge, stat); + + /* Mail box irqs */ + if (stat & (TSI148_LCSR_INTS_MB3S | TSI148_LCSR_INTS_MB2S | + TSI148_LCSR_INTS_MB1S | TSI148_LCSR_INTS_MB0S)) + serviced |= tsi148_MB_irqhandler(tsi148_bridge, stat); + + /* PCI bus error */ + if (stat & TSI148_LCSR_INTS_PERRS) + serviced |= tsi148_PERR_irqhandler(tsi148_bridge); + + /* VME bus error */ + if (stat & TSI148_LCSR_INTS_VERRS) + serviced |= tsi148_VERR_irqhandler(tsi148_bridge); + + /* IACK irq */ + if (stat & TSI148_LCSR_INTS_IACKS) + serviced |= tsi148_IACK_irqhandler(bridge); + + /* VME bus irqs */ + if (stat & (TSI148_LCSR_INTS_IRQ7S | TSI148_LCSR_INTS_IRQ6S | + TSI148_LCSR_INTS_IRQ5S | TSI148_LCSR_INTS_IRQ4S | + TSI148_LCSR_INTS_IRQ3S | TSI148_LCSR_INTS_IRQ2S | + TSI148_LCSR_INTS_IRQ1S)) + serviced |= tsi148_VIRQ_irqhandler(tsi148_bridge, stat); + + /* Clear serviced interrupts */ + iowrite32be(serviced, bridge->base + TSI148_LCSR_INTC); + + return IRQ_HANDLED; +} + +static int tsi148_irq_init(struct vme_bridge *tsi148_bridge) +{ + int result; + unsigned int tmp; + struct pci_dev *pdev; + struct tsi148_driver *bridge; + + pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + + bridge = tsi148_bridge->driver_priv; + + /* Initialise list for VME bus errors */ + INIT_LIST_HEAD(&tsi148_bridge->vme_errors); + + mutex_init(&tsi148_bridge->irq_mtx); + + result = request_irq(pdev->irq, + tsi148_irqhandler, + IRQF_SHARED, + driver_name, tsi148_bridge); + if (result) { + dev_err(tsi148_bridge->parent, "Can't get assigned pci irq " + "vector %02X\n", pdev->irq); + return result; + } + + /* Enable and unmask interrupts */ + tmp = TSI148_LCSR_INTEO_DMA1EO | TSI148_LCSR_INTEO_DMA0EO | + TSI148_LCSR_INTEO_MB3EO | TSI148_LCSR_INTEO_MB2EO | + TSI148_LCSR_INTEO_MB1EO | TSI148_LCSR_INTEO_MB0EO | + TSI148_LCSR_INTEO_PERREO | TSI148_LCSR_INTEO_VERREO | + TSI148_LCSR_INTEO_IACKEO; + + /* This leaves the following interrupts masked. + * TSI148_LCSR_INTEO_VIEEO + * TSI148_LCSR_INTEO_SYSFLEO + * TSI148_LCSR_INTEO_ACFLEO + */ + + /* Don't enable Location Monitor interrupts here - they will be + * enabled when the location monitors are properly configured and + * a callback has been attached. + * TSI148_LCSR_INTEO_LM0EO + * TSI148_LCSR_INTEO_LM1EO + * TSI148_LCSR_INTEO_LM2EO + * TSI148_LCSR_INTEO_LM3EO + */ + + /* Don't enable VME interrupts until we add a handler, else the board + * will respond to it and we don't want that unless it knows how to + * properly deal with it. + * TSI148_LCSR_INTEO_IRQ7EO + * TSI148_LCSR_INTEO_IRQ6EO + * TSI148_LCSR_INTEO_IRQ5EO + * TSI148_LCSR_INTEO_IRQ4EO + * TSI148_LCSR_INTEO_IRQ3EO + * TSI148_LCSR_INTEO_IRQ2EO + * TSI148_LCSR_INTEO_IRQ1EO + */ + + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); + + return 0; +} + +static void tsi148_irq_exit(struct vme_bridge *tsi148_bridge, + struct pci_dev *pdev) +{ + struct tsi148_driver *bridge = tsi148_bridge->driver_priv; + + /* Turn off interrupts */ + iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEO); + iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEN); + + /* Clear all interrupts */ + iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_INTC); + + /* Detach interrupt handler */ + free_irq(pdev->irq, tsi148_bridge); +} + +/* + * Check to see if an IACk has been received, return true (1) or false (0). + */ +static int tsi148_iack_received(struct tsi148_driver *bridge) +{ + u32 tmp; + + tmp = ioread32be(bridge->base + TSI148_LCSR_VICR); + + if (tmp & TSI148_LCSR_VICR_IRQS) + return 0; + else + return 1; +} + +/* + * Configure VME interrupt + */ +static void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level, + int state, int sync) +{ + struct pci_dev *pdev; + u32 tmp; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + /* We need to do the ordering differently for enabling and disabling */ + if (state == 0) { + tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); + tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1]; + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); + + tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); + tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1]; + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); + + if (sync != 0) { + pdev = container_of(tsi148_bridge->parent, + struct pci_dev, dev); + + synchronize_irq(pdev->irq); + } + } else { + tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); + tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1]; + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); + + tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); + tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1]; + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); + } +} + +/* + * Generate a VME bus interrupt at the requested level & vector. Wait for + * interrupt to be acked. + */ +static int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level, + int statid) +{ + u32 tmp; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + mutex_lock(&bridge->vme_int); + + /* Read VICR register */ + tmp = ioread32be(bridge->base + TSI148_LCSR_VICR); + + /* Set Status/ID */ + tmp = (tmp & ~TSI148_LCSR_VICR_STID_M) | + (statid & TSI148_LCSR_VICR_STID_M); + iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR); + + /* Assert VMEbus IRQ */ + tmp = tmp | TSI148_LCSR_VICR_IRQL[level]; + iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR); + + /* XXX Consider implementing a timeout? */ + wait_event_interruptible(bridge->iack_queue, + tsi148_iack_received(bridge)); + + mutex_unlock(&bridge->vme_int); + + return 0; +} + +/* + * Find the first error in this address range + */ +static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge, + u32 aspace, unsigned long long address, size_t count) +{ + struct list_head *err_pos; + struct vme_bus_error *vme_err, *valid = NULL; + unsigned long long bound; + + bound = address + count; + + /* + * XXX We are currently not looking at the address space when parsing + * for errors. This is because parsing the Address Modifier Codes + * is going to be quite resource intensive to do properly. We + * should be OK just looking at the addresses and this is certainly + * much better than what we had before. + */ + err_pos = NULL; + /* Iterate through errors */ + list_for_each(err_pos, &tsi148_bridge->vme_errors) { + vme_err = list_entry(err_pos, struct vme_bus_error, list); + if ((vme_err->address >= address) && + (vme_err->address < bound)) { + + valid = vme_err; + break; + } + } + + return valid; +} + +/* + * Clear errors in the provided address range. + */ +static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge, + u32 aspace, unsigned long long address, size_t count) +{ + struct list_head *err_pos, *temp; + struct vme_bus_error *vme_err; + unsigned long long bound; + + bound = address + count; + + /* + * XXX We are currently not looking at the address space when parsing + * for errors. This is because parsing the Address Modifier Codes + * is going to be quite resource intensive to do properly. We + * should be OK just looking at the addresses and this is certainly + * much better than what we had before. + */ + err_pos = NULL; + /* Iterate through errors */ + list_for_each_safe(err_pos, temp, &tsi148_bridge->vme_errors) { + vme_err = list_entry(err_pos, struct vme_bus_error, list); + + if ((vme_err->address >= address) && + (vme_err->address < bound)) { + + list_del(err_pos); + kfree(vme_err); + } + } +} + +/* + * Initialize a slave window with the requested attributes. + */ +static int tsi148_slave_set(struct vme_slave_resource *image, int enabled, + unsigned long long vme_base, unsigned long long size, + dma_addr_t pci_base, u32 aspace, u32 cycle) +{ + unsigned int i, addr = 0, granularity = 0; + unsigned int temp_ctl = 0; + unsigned int vme_base_low, vme_base_high; + unsigned int vme_bound_low, vme_bound_high; + unsigned int pci_offset_low, pci_offset_high; + unsigned long long vme_bound, pci_offset; + struct vme_bridge *tsi148_bridge; + struct tsi148_driver *bridge; + + tsi148_bridge = image->parent; + bridge = tsi148_bridge->driver_priv; + + i = image->number; + + switch (aspace) { + case VME_A16: + granularity = 0x10; + addr |= TSI148_LCSR_ITAT_AS_A16; + break; + case VME_A24: + granularity = 0x1000; + addr |= TSI148_LCSR_ITAT_AS_A24; + break; + case VME_A32: + granularity = 0x10000; + addr |= TSI148_LCSR_ITAT_AS_A32; + break; + case VME_A64: + granularity = 0x10000; + addr |= TSI148_LCSR_ITAT_AS_A64; + break; + case VME_CRCSR: + case VME_USER1: + case VME_USER2: + case VME_USER3: + case VME_USER4: + default: + dev_err(tsi148_bridge->parent, "Invalid address space\n"); + return -EINVAL; + break; + } + + /* Convert 64-bit variables to 2x 32-bit variables */ + reg_split(vme_base, &vme_base_high, &vme_base_low); + + /* + * Bound address is a valid address for the window, adjust + * accordingly + */ + vme_bound = vme_base + size - granularity; + reg_split(vme_bound, &vme_bound_high, &vme_bound_low); + pci_offset = (unsigned long long)pci_base - vme_base; + reg_split(pci_offset, &pci_offset_high, &pci_offset_low); + + if (vme_base_low & (granularity - 1)) { + dev_err(tsi148_bridge->parent, "Invalid VME base alignment\n"); + return -EINVAL; + } + if (vme_bound_low & (granularity - 1)) { + dev_err(tsi148_bridge->parent, "Invalid VME bound alignment\n"); + return -EINVAL; + } + if (pci_offset_low & (granularity - 1)) { + dev_err(tsi148_bridge->parent, "Invalid PCI Offset " + "alignment\n"); + return -EINVAL; + } + + /* Disable while we are mucking around */ + temp_ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITAT); + temp_ctl &= ~TSI148_LCSR_ITAT_EN; + iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITAT); + + /* Setup mapping */ + iowrite32be(vme_base_high, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITSAU); + iowrite32be(vme_base_low, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITSAL); + iowrite32be(vme_bound_high, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITEAU); + iowrite32be(vme_bound_low, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITEAL); + iowrite32be(pci_offset_high, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITOFU); + iowrite32be(pci_offset_low, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITOFL); + + /* Setup 2eSST speeds */ + temp_ctl &= ~TSI148_LCSR_ITAT_2eSSTM_M; + switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { + case VME_2eSST160: + temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_160; + break; + case VME_2eSST267: + temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_267; + break; + case VME_2eSST320: + temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_320; + break; + } + + /* Setup cycle types */ + temp_ctl &= ~(0x1F << 7); + if (cycle & VME_BLT) + temp_ctl |= TSI148_LCSR_ITAT_BLT; + if (cycle & VME_MBLT) + temp_ctl |= TSI148_LCSR_ITAT_MBLT; + if (cycle & VME_2eVME) + temp_ctl |= TSI148_LCSR_ITAT_2eVME; + if (cycle & VME_2eSST) + temp_ctl |= TSI148_LCSR_ITAT_2eSST; + if (cycle & VME_2eSSTB) + temp_ctl |= TSI148_LCSR_ITAT_2eSSTB; + + /* Setup address space */ + temp_ctl &= ~TSI148_LCSR_ITAT_AS_M; + temp_ctl |= addr; + + temp_ctl &= ~0xF; + if (cycle & VME_SUPER) + temp_ctl |= TSI148_LCSR_ITAT_SUPR ; + if (cycle & VME_USER) + temp_ctl |= TSI148_LCSR_ITAT_NPRIV; + if (cycle & VME_PROG) + temp_ctl |= TSI148_LCSR_ITAT_PGM; + if (cycle & VME_DATA) + temp_ctl |= TSI148_LCSR_ITAT_DATA; + + /* Write ctl reg without enable */ + iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITAT); + + if (enabled) + temp_ctl |= TSI148_LCSR_ITAT_EN; + + iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITAT); + + return 0; +} + +/* + * Get slave window configuration. + */ +static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, + dma_addr_t *pci_base, u32 *aspace, u32 *cycle) +{ + unsigned int i, granularity = 0, ctl = 0; + unsigned int vme_base_low, vme_base_high; + unsigned int vme_bound_low, vme_bound_high; + unsigned int pci_offset_low, pci_offset_high; + unsigned long long vme_bound, pci_offset; + struct tsi148_driver *bridge; + + bridge = image->parent->driver_priv; + + i = image->number; + + /* Read registers */ + ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITAT); + + vme_base_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITSAU); + vme_base_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITSAL); + vme_bound_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITEAU); + vme_bound_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITEAL); + pci_offset_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITOFU); + pci_offset_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITOFL); + + /* Convert 64-bit variables to 2x 32-bit variables */ + reg_join(vme_base_high, vme_base_low, vme_base); + reg_join(vme_bound_high, vme_bound_low, &vme_bound); + reg_join(pci_offset_high, pci_offset_low, &pci_offset); + + *pci_base = (dma_addr_t)vme_base + pci_offset; + + *enabled = 0; + *aspace = 0; + *cycle = 0; + + if (ctl & TSI148_LCSR_ITAT_EN) + *enabled = 1; + + if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A16) { + granularity = 0x10; + *aspace |= VME_A16; + } + if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A24) { + granularity = 0x1000; + *aspace |= VME_A24; + } + if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A32) { + granularity = 0x10000; + *aspace |= VME_A32; + } + if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A64) { + granularity = 0x10000; + *aspace |= VME_A64; + } + + /* Need granularity before we set the size */ + *size = (unsigned long long)((vme_bound - *vme_base) + granularity); + + + if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_160) + *cycle |= VME_2eSST160; + if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_267) + *cycle |= VME_2eSST267; + if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_320) + *cycle |= VME_2eSST320; + + if (ctl & TSI148_LCSR_ITAT_BLT) + *cycle |= VME_BLT; + if (ctl & TSI148_LCSR_ITAT_MBLT) + *cycle |= VME_MBLT; + if (ctl & TSI148_LCSR_ITAT_2eVME) + *cycle |= VME_2eVME; + if (ctl & TSI148_LCSR_ITAT_2eSST) + *cycle |= VME_2eSST; + if (ctl & TSI148_LCSR_ITAT_2eSSTB) + *cycle |= VME_2eSSTB; + + if (ctl & TSI148_LCSR_ITAT_SUPR) + *cycle |= VME_SUPER; + if (ctl & TSI148_LCSR_ITAT_NPRIV) + *cycle |= VME_USER; + if (ctl & TSI148_LCSR_ITAT_PGM) + *cycle |= VME_PROG; + if (ctl & TSI148_LCSR_ITAT_DATA) + *cycle |= VME_DATA; + + return 0; +} + +/* + * Allocate and map PCI Resource + */ +static int tsi148_alloc_resource(struct vme_master_resource *image, + unsigned long long size) +{ + unsigned long long existing_size; + int retval = 0; + struct pci_dev *pdev; + struct vme_bridge *tsi148_bridge; + + tsi148_bridge = image->parent; + + pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + + existing_size = (unsigned long long)(image->bus_resource.end - + image->bus_resource.start); + + /* If the existing size is OK, return */ + if ((size != 0) && (existing_size == (size - 1))) + return 0; + + if (existing_size != 0) { + iounmap(image->kern_base); + image->kern_base = NULL; + kfree(image->bus_resource.name); + release_resource(&image->bus_resource); + memset(&image->bus_resource, 0, sizeof(struct resource)); + } + + /* Exit here if size is zero */ + if (size == 0) + return 0; + + if (image->bus_resource.name == NULL) { + image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); + if (image->bus_resource.name == NULL) { + dev_err(tsi148_bridge->parent, "Unable to allocate " + "memory for resource name\n"); + retval = -ENOMEM; + goto err_name; + } + } + + sprintf((char *)image->bus_resource.name, "%s.%d", tsi148_bridge->name, + image->number); + + image->bus_resource.start = 0; + image->bus_resource.end = (unsigned long)size; + image->bus_resource.flags = IORESOURCE_MEM; + + retval = pci_bus_alloc_resource(pdev->bus, + &image->bus_resource, size, size, PCIBIOS_MIN_MEM, + 0, NULL, NULL); + if (retval) { + dev_err(tsi148_bridge->parent, "Failed to allocate mem " + "resource for window %d size 0x%lx start 0x%lx\n", + image->number, (unsigned long)size, + (unsigned long)image->bus_resource.start); + goto err_resource; + } + + image->kern_base = ioremap_nocache( + image->bus_resource.start, size); + if (image->kern_base == NULL) { + dev_err(tsi148_bridge->parent, "Failed to remap resource\n"); + retval = -ENOMEM; + goto err_remap; + } + + return 0; + +err_remap: + release_resource(&image->bus_resource); +err_resource: + kfree(image->bus_resource.name); + memset(&image->bus_resource, 0, sizeof(struct resource)); +err_name: + return retval; +} + +/* + * Free and unmap PCI Resource + */ +static void tsi148_free_resource(struct vme_master_resource *image) +{ + iounmap(image->kern_base); + image->kern_base = NULL; + release_resource(&image->bus_resource); + kfree(image->bus_resource.name); + memset(&image->bus_resource, 0, sizeof(struct resource)); +} + +/* + * Set the attributes of an outbound window. + */ +static int tsi148_master_set(struct vme_master_resource *image, int enabled, + unsigned long long vme_base, unsigned long long size, u32 aspace, + u32 cycle, u32 dwidth) +{ + int retval = 0; + unsigned int i; + unsigned int temp_ctl = 0; + unsigned int pci_base_low, pci_base_high; + unsigned int pci_bound_low, pci_bound_high; + unsigned int vme_offset_low, vme_offset_high; + unsigned long long pci_bound, vme_offset, pci_base; + struct vme_bridge *tsi148_bridge; + struct tsi148_driver *bridge; + + tsi148_bridge = image->parent; + + bridge = tsi148_bridge->driver_priv; + + /* Verify input data */ + if (vme_base & 0xFFFF) { + dev_err(tsi148_bridge->parent, "Invalid VME Window " + "alignment\n"); + retval = -EINVAL; + goto err_window; + } + + if ((size == 0) && (enabled != 0)) { + dev_err(tsi148_bridge->parent, "Size must be non-zero for " + "enabled windows\n"); + retval = -EINVAL; + goto err_window; + } + + spin_lock(&image->lock); + + /* Let's allocate the resource here rather than further up the stack as + * it avoids pushing loads of bus dependent stuff up the stack. If size + * is zero, any existing resource will be freed. + */ + retval = tsi148_alloc_resource(image, size); + if (retval) { + spin_unlock(&image->lock); + dev_err(tsi148_bridge->parent, "Unable to allocate memory for " + "resource\n"); + goto err_res; + } + + if (size == 0) { + pci_base = 0; + pci_bound = 0; + vme_offset = 0; + } else { + pci_base = (unsigned long long)image->bus_resource.start; + + /* + * Bound address is a valid address for the window, adjust + * according to window granularity. + */ + pci_bound = pci_base + (size - 0x10000); + vme_offset = vme_base - pci_base; + } + + /* Convert 64-bit variables to 2x 32-bit variables */ + reg_split(pci_base, &pci_base_high, &pci_base_low); + reg_split(pci_bound, &pci_bound_high, &pci_bound_low); + reg_split(vme_offset, &vme_offset_high, &vme_offset_low); + + if (pci_base_low & 0xFFFF) { + spin_unlock(&image->lock); + dev_err(tsi148_bridge->parent, "Invalid PCI base alignment\n"); + retval = -EINVAL; + goto err_gran; + } + if (pci_bound_low & 0xFFFF) { + spin_unlock(&image->lock); + dev_err(tsi148_bridge->parent, "Invalid PCI bound alignment\n"); + retval = -EINVAL; + goto err_gran; + } + if (vme_offset_low & 0xFFFF) { + spin_unlock(&image->lock); + dev_err(tsi148_bridge->parent, "Invalid VME Offset " + "alignment\n"); + retval = -EINVAL; + goto err_gran; + } + + i = image->number; + + /* Disable while we are mucking around */ + temp_ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTAT); + temp_ctl &= ~TSI148_LCSR_OTAT_EN; + iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTAT); + + /* Setup 2eSST speeds */ + temp_ctl &= ~TSI148_LCSR_OTAT_2eSSTM_M; + switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { + case VME_2eSST160: + temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_160; + break; + case VME_2eSST267: + temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_267; + break; + case VME_2eSST320: + temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_320; + break; + } + + /* Setup cycle types */ + if (cycle & VME_BLT) { + temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; + temp_ctl |= TSI148_LCSR_OTAT_TM_BLT; + } + if (cycle & VME_MBLT) { + temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; + temp_ctl |= TSI148_LCSR_OTAT_TM_MBLT; + } + if (cycle & VME_2eVME) { + temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; + temp_ctl |= TSI148_LCSR_OTAT_TM_2eVME; + } + if (cycle & VME_2eSST) { + temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; + temp_ctl |= TSI148_LCSR_OTAT_TM_2eSST; + } + if (cycle & VME_2eSSTB) { + dev_warn(tsi148_bridge->parent, "Currently not setting " + "Broadcast Select Registers\n"); + temp_ctl &= ~TSI148_LCSR_OTAT_TM_M; + temp_ctl |= TSI148_LCSR_OTAT_TM_2eSSTB; + } + + /* Setup data width */ + temp_ctl &= ~TSI148_LCSR_OTAT_DBW_M; + switch (dwidth) { + case VME_D16: + temp_ctl |= TSI148_LCSR_OTAT_DBW_16; + break; + case VME_D32: + temp_ctl |= TSI148_LCSR_OTAT_DBW_32; + break; + default: + spin_unlock(&image->lock); + dev_err(tsi148_bridge->parent, "Invalid data width\n"); + retval = -EINVAL; + goto err_dwidth; + } + + /* Setup address space */ + temp_ctl &= ~TSI148_LCSR_OTAT_AMODE_M; + switch (aspace) { + case VME_A16: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_A16; + break; + case VME_A24: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_A24; + break; + case VME_A32: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_A32; + break; + case VME_A64: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_A64; + break; + case VME_CRCSR: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_CRCSR; + break; + case VME_USER1: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER1; + break; + case VME_USER2: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER2; + break; + case VME_USER3: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER3; + break; + case VME_USER4: + temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER4; + break; + default: + spin_unlock(&image->lock); + dev_err(tsi148_bridge->parent, "Invalid address space\n"); + retval = -EINVAL; + goto err_aspace; + break; + } + + temp_ctl &= ~(3<<4); + if (cycle & VME_SUPER) + temp_ctl |= TSI148_LCSR_OTAT_SUP; + if (cycle & VME_PROG) + temp_ctl |= TSI148_LCSR_OTAT_PGM; + + /* Setup mapping */ + iowrite32be(pci_base_high, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTSAU); + iowrite32be(pci_base_low, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTSAL); + iowrite32be(pci_bound_high, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTEAU); + iowrite32be(pci_bound_low, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTEAL); + iowrite32be(vme_offset_high, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTOFU); + iowrite32be(vme_offset_low, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTOFL); + + /* Write ctl reg without enable */ + iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTAT); + + if (enabled) + temp_ctl |= TSI148_LCSR_OTAT_EN; + + iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTAT); + + spin_unlock(&image->lock); + return 0; + +err_aspace: +err_dwidth: +err_gran: + tsi148_free_resource(image); +err_res: +err_window: + return retval; + +} + +/* + * Set the attributes of an outbound window. + * + * XXX Not parsing prefetch information. + */ +static int __tsi148_master_get(struct vme_master_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *dwidth) +{ + unsigned int i, ctl; + unsigned int pci_base_low, pci_base_high; + unsigned int pci_bound_low, pci_bound_high; + unsigned int vme_offset_low, vme_offset_high; + + unsigned long long pci_base, pci_bound, vme_offset; + struct tsi148_driver *bridge; + + bridge = image->parent->driver_priv; + + i = image->number; + + ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTAT); + + pci_base_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTSAU); + pci_base_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTSAL); + pci_bound_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTEAU); + pci_bound_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTEAL); + vme_offset_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTOFU); + vme_offset_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTOFL); + + /* Convert 64-bit variables to 2x 32-bit variables */ + reg_join(pci_base_high, pci_base_low, &pci_base); + reg_join(pci_bound_high, pci_bound_low, &pci_bound); + reg_join(vme_offset_high, vme_offset_low, &vme_offset); + + *vme_base = pci_base + vme_offset; + *size = (unsigned long long)(pci_bound - pci_base) + 0x10000; + + *enabled = 0; + *aspace = 0; + *cycle = 0; + *dwidth = 0; + + if (ctl & TSI148_LCSR_OTAT_EN) + *enabled = 1; + + /* Setup address space */ + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A16) + *aspace |= VME_A16; + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A24) + *aspace |= VME_A24; + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A32) + *aspace |= VME_A32; + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A64) + *aspace |= VME_A64; + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_CRCSR) + *aspace |= VME_CRCSR; + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER1) + *aspace |= VME_USER1; + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER2) + *aspace |= VME_USER2; + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER3) + *aspace |= VME_USER3; + if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER4) + *aspace |= VME_USER4; + + /* Setup 2eSST speeds */ + if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_160) + *cycle |= VME_2eSST160; + if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_267) + *cycle |= VME_2eSST267; + if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_320) + *cycle |= VME_2eSST320; + + /* Setup cycle types */ + if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_SCT) + *cycle |= VME_SCT; + if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_BLT) + *cycle |= VME_BLT; + if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_MBLT) + *cycle |= VME_MBLT; + if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eVME) + *cycle |= VME_2eVME; + if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSST) + *cycle |= VME_2eSST; + if ((ctl & TSI148_LCSR_OTAT_TM_M) == TSI148_LCSR_OTAT_TM_2eSSTB) + *cycle |= VME_2eSSTB; + + if (ctl & TSI148_LCSR_OTAT_SUP) + *cycle |= VME_SUPER; + else + *cycle |= VME_USER; + + if (ctl & TSI148_LCSR_OTAT_PGM) + *cycle |= VME_PROG; + else + *cycle |= VME_DATA; + + /* Setup data width */ + if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_16) + *dwidth = VME_D16; + if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_32) + *dwidth = VME_D32; + + return 0; +} + + +static int tsi148_master_get(struct vme_master_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *dwidth) +{ + int retval; + + spin_lock(&image->lock); + + retval = __tsi148_master_get(image, enabled, vme_base, size, aspace, + cycle, dwidth); + + spin_unlock(&image->lock); + + return retval; +} + +static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, + size_t count, loff_t offset) +{ + int retval, enabled; + unsigned long long vme_base, size; + u32 aspace, cycle, dwidth; + struct vme_bus_error *vme_err = NULL; + struct vme_bridge *tsi148_bridge; + + tsi148_bridge = image->parent; + + spin_lock(&image->lock); + + memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count); + retval = count; + + if (!err_chk) + goto skip_chk; + + __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, + &dwidth); + + vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, + count); + if (vme_err != NULL) { + dev_err(image->parent->parent, "First VME read error detected " + "an at address 0x%llx\n", vme_err->address); + retval = vme_err->address - (vme_base + offset); + /* Clear down save errors in this address range */ + tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, + count); + } + +skip_chk: + spin_unlock(&image->lock); + + return retval; +} + + +static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, + size_t count, loff_t offset) +{ + int retval = 0, enabled; + unsigned long long vme_base, size; + u32 aspace, cycle, dwidth; + + struct vme_bus_error *vme_err = NULL; + struct vme_bridge *tsi148_bridge; + struct tsi148_driver *bridge; + + tsi148_bridge = image->parent; + + bridge = tsi148_bridge->driver_priv; + + spin_lock(&image->lock); + + memcpy_toio(image->kern_base + offset, buf, (unsigned int)count); + retval = count; + + /* + * Writes are posted. We need to do a read on the VME bus to flush out + * all of the writes before we check for errors. We can't guarantee + * that reading the data we have just written is safe. It is believed + * that there isn't any read, write re-ordering, so we can read any + * location in VME space, so lets read the Device ID from the tsi148's + * own registers as mapped into CR/CSR space. + * + * We check for saved errors in the written address range/space. + */ + + if (!err_chk) + goto skip_chk; + + /* + * Get window info first, to maximise the time that the buffers may + * fluch on their own + */ + __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, + &dwidth); + + ioread16(bridge->flush_image->kern_base + 0x7F000); + + vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, + count); + if (vme_err != NULL) { + dev_warn(tsi148_bridge->parent, "First VME write error detected" + " an at address 0x%llx\n", vme_err->address); + retval = vme_err->address - (vme_base + offset); + /* Clear down save errors in this address range */ + tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, + count); + } + +skip_chk: + spin_unlock(&image->lock); + + return retval; +} + +/* + * Perform an RMW cycle on the VME bus. + * + * Requires a previously configured master window, returns final value. + */ +static unsigned int tsi148_master_rmw(struct vme_master_resource *image, + unsigned int mask, unsigned int compare, unsigned int swap, + loff_t offset) +{ + unsigned long long pci_addr; + unsigned int pci_addr_high, pci_addr_low; + u32 tmp, result; + int i; + struct tsi148_driver *bridge; + + bridge = image->parent->driver_priv; + + /* Find the PCI address that maps to the desired VME address */ + i = image->number; + + /* Locking as we can only do one of these at a time */ + mutex_lock(&bridge->vme_rmw); + + /* Lock image */ + spin_lock(&image->lock); + + pci_addr_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTSAU); + pci_addr_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTSAL); + + reg_join(pci_addr_high, pci_addr_low, &pci_addr); + reg_split(pci_addr + offset, &pci_addr_high, &pci_addr_low); + + /* Configure registers */ + iowrite32be(mask, bridge->base + TSI148_LCSR_RMWEN); + iowrite32be(compare, bridge->base + TSI148_LCSR_RMWC); + iowrite32be(swap, bridge->base + TSI148_LCSR_RMWS); + iowrite32be(pci_addr_high, bridge->base + TSI148_LCSR_RMWAU); + iowrite32be(pci_addr_low, bridge->base + TSI148_LCSR_RMWAL); + + /* Enable RMW */ + tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL); + tmp |= TSI148_LCSR_VMCTRL_RMWEN; + iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL); + + /* Kick process off with a read to the required address. */ + result = ioread32be(image->kern_base + offset); + + /* Disable RMW */ + tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL); + tmp &= ~TSI148_LCSR_VMCTRL_RMWEN; + iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL); + + spin_unlock(&image->lock); + + mutex_unlock(&bridge->vme_rmw); + + return result; +} + +static int tsi148_dma_set_vme_src_attributes(struct device *dev, __be32 *attr, + u32 aspace, u32 cycle, u32 dwidth) +{ + u32 val; + + val = be32_to_cpu(*attr); + + /* Setup 2eSST speeds */ + switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { + case VME_2eSST160: + val |= TSI148_LCSR_DSAT_2eSSTM_160; + break; + case VME_2eSST267: + val |= TSI148_LCSR_DSAT_2eSSTM_267; + break; + case VME_2eSST320: + val |= TSI148_LCSR_DSAT_2eSSTM_320; + break; + } + + /* Setup cycle types */ + if (cycle & VME_SCT) + val |= TSI148_LCSR_DSAT_TM_SCT; + + if (cycle & VME_BLT) + val |= TSI148_LCSR_DSAT_TM_BLT; + + if (cycle & VME_MBLT) + val |= TSI148_LCSR_DSAT_TM_MBLT; + + if (cycle & VME_2eVME) + val |= TSI148_LCSR_DSAT_TM_2eVME; + + if (cycle & VME_2eSST) + val |= TSI148_LCSR_DSAT_TM_2eSST; + + if (cycle & VME_2eSSTB) { + dev_err(dev, "Currently not setting Broadcast Select " + "Registers\n"); + val |= TSI148_LCSR_DSAT_TM_2eSSTB; + } + + /* Setup data width */ + switch (dwidth) { + case VME_D16: + val |= TSI148_LCSR_DSAT_DBW_16; + break; + case VME_D32: + val |= TSI148_LCSR_DSAT_DBW_32; + break; + default: + dev_err(dev, "Invalid data width\n"); + return -EINVAL; + } + + /* Setup address space */ + switch (aspace) { + case VME_A16: + val |= TSI148_LCSR_DSAT_AMODE_A16; + break; + case VME_A24: + val |= TSI148_LCSR_DSAT_AMODE_A24; + break; + case VME_A32: + val |= TSI148_LCSR_DSAT_AMODE_A32; + break; + case VME_A64: + val |= TSI148_LCSR_DSAT_AMODE_A64; + break; + case VME_CRCSR: + val |= TSI148_LCSR_DSAT_AMODE_CRCSR; + break; + case VME_USER1: + val |= TSI148_LCSR_DSAT_AMODE_USER1; + break; + case VME_USER2: + val |= TSI148_LCSR_DSAT_AMODE_USER2; + break; + case VME_USER3: + val |= TSI148_LCSR_DSAT_AMODE_USER3; + break; + case VME_USER4: + val |= TSI148_LCSR_DSAT_AMODE_USER4; + break; + default: + dev_err(dev, "Invalid address space\n"); + return -EINVAL; + break; + } + + if (cycle & VME_SUPER) + val |= TSI148_LCSR_DSAT_SUP; + if (cycle & VME_PROG) + val |= TSI148_LCSR_DSAT_PGM; + + *attr = cpu_to_be32(val); + + return 0; +} + +static int tsi148_dma_set_vme_dest_attributes(struct device *dev, __be32 *attr, + u32 aspace, u32 cycle, u32 dwidth) +{ + u32 val; + + val = be32_to_cpu(*attr); + + /* Setup 2eSST speeds */ + switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) { + case VME_2eSST160: + val |= TSI148_LCSR_DDAT_2eSSTM_160; + break; + case VME_2eSST267: + val |= TSI148_LCSR_DDAT_2eSSTM_267; + break; + case VME_2eSST320: + val |= TSI148_LCSR_DDAT_2eSSTM_320; + break; + } + + /* Setup cycle types */ + if (cycle & VME_SCT) + val |= TSI148_LCSR_DDAT_TM_SCT; + + if (cycle & VME_BLT) + val |= TSI148_LCSR_DDAT_TM_BLT; + + if (cycle & VME_MBLT) + val |= TSI148_LCSR_DDAT_TM_MBLT; + + if (cycle & VME_2eVME) + val |= TSI148_LCSR_DDAT_TM_2eVME; + + if (cycle & VME_2eSST) + val |= TSI148_LCSR_DDAT_TM_2eSST; + + if (cycle & VME_2eSSTB) { + dev_err(dev, "Currently not setting Broadcast Select " + "Registers\n"); + val |= TSI148_LCSR_DDAT_TM_2eSSTB; + } + + /* Setup data width */ + switch (dwidth) { + case VME_D16: + val |= TSI148_LCSR_DDAT_DBW_16; + break; + case VME_D32: + val |= TSI148_LCSR_DDAT_DBW_32; + break; + default: + dev_err(dev, "Invalid data width\n"); + return -EINVAL; + } + + /* Setup address space */ + switch (aspace) { + case VME_A16: + val |= TSI148_LCSR_DDAT_AMODE_A16; + break; + case VME_A24: + val |= TSI148_LCSR_DDAT_AMODE_A24; + break; + case VME_A32: + val |= TSI148_LCSR_DDAT_AMODE_A32; + break; + case VME_A64: + val |= TSI148_LCSR_DDAT_AMODE_A64; + break; + case VME_CRCSR: + val |= TSI148_LCSR_DDAT_AMODE_CRCSR; + break; + case VME_USER1: + val |= TSI148_LCSR_DDAT_AMODE_USER1; + break; + case VME_USER2: + val |= TSI148_LCSR_DDAT_AMODE_USER2; + break; + case VME_USER3: + val |= TSI148_LCSR_DDAT_AMODE_USER3; + break; + case VME_USER4: + val |= TSI148_LCSR_DDAT_AMODE_USER4; + break; + default: + dev_err(dev, "Invalid address space\n"); + return -EINVAL; + break; + } + + if (cycle & VME_SUPER) + val |= TSI148_LCSR_DDAT_SUP; + if (cycle & VME_PROG) + val |= TSI148_LCSR_DDAT_PGM; + + *attr = cpu_to_be32(val); + + return 0; +} + +/* + * Add a link list descriptor to the list + * + * Note: DMA engine expects the DMA descriptor to be big endian. + */ +static int tsi148_dma_list_add(struct vme_dma_list *list, + struct vme_dma_attr *src, struct vme_dma_attr *dest, size_t count) +{ + struct tsi148_dma_entry *entry, *prev; + u32 address_high, address_low, val; + struct vme_dma_pattern *pattern_attr; + struct vme_dma_pci *pci_attr; + struct vme_dma_vme *vme_attr; + int retval = 0; + struct vme_bridge *tsi148_bridge; + + tsi148_bridge = list->parent->parent; + + /* Descriptor must be aligned on 64-bit boundaries */ + entry = kmalloc(sizeof(struct tsi148_dma_entry), GFP_KERNEL); + if (entry == NULL) { + dev_err(tsi148_bridge->parent, "Failed to allocate memory for " + "dma resource structure\n"); + retval = -ENOMEM; + goto err_mem; + } + + /* Test descriptor alignment */ + if ((unsigned long)&entry->descriptor & 0x7) { + dev_err(tsi148_bridge->parent, "Descriptor not aligned to 8 " + "byte boundary as required: %p\n", + &entry->descriptor); + retval = -EINVAL; + goto err_align; + } + + /* Given we are going to fill out the structure, we probably don't + * need to zero it, but better safe than sorry for now. + */ + memset(&entry->descriptor, 0, sizeof(struct tsi148_dma_descriptor)); + + /* Fill out source part */ + switch (src->type) { + case VME_DMA_PATTERN: + pattern_attr = src->private; + + entry->descriptor.dsal = cpu_to_be32(pattern_attr->pattern); + + val = TSI148_LCSR_DSAT_TYP_PAT; + + /* Default behaviour is 32 bit pattern */ + if (pattern_attr->type & VME_DMA_PATTERN_BYTE) + val |= TSI148_LCSR_DSAT_PSZ; + + /* It seems that the default behaviour is to increment */ + if ((pattern_attr->type & VME_DMA_PATTERN_INCREMENT) == 0) + val |= TSI148_LCSR_DSAT_NIN; + entry->descriptor.dsat = cpu_to_be32(val); + break; + case VME_DMA_PCI: + pci_attr = src->private; + + reg_split((unsigned long long)pci_attr->address, &address_high, + &address_low); + entry->descriptor.dsau = cpu_to_be32(address_high); + entry->descriptor.dsal = cpu_to_be32(address_low); + entry->descriptor.dsat = cpu_to_be32(TSI148_LCSR_DSAT_TYP_PCI); + break; + case VME_DMA_VME: + vme_attr = src->private; + + reg_split((unsigned long long)vme_attr->address, &address_high, + &address_low); + entry->descriptor.dsau = cpu_to_be32(address_high); + entry->descriptor.dsal = cpu_to_be32(address_low); + entry->descriptor.dsat = cpu_to_be32(TSI148_LCSR_DSAT_TYP_VME); + + retval = tsi148_dma_set_vme_src_attributes( + tsi148_bridge->parent, &entry->descriptor.dsat, + vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth); + if (retval < 0) + goto err_source; + break; + default: + dev_err(tsi148_bridge->parent, "Invalid source type\n"); + retval = -EINVAL; + goto err_source; + break; + } + + /* Assume last link - this will be over-written by adding another */ + entry->descriptor.dnlau = cpu_to_be32(0); + entry->descriptor.dnlal = cpu_to_be32(TSI148_LCSR_DNLAL_LLA); + + /* Fill out destination part */ + switch (dest->type) { + case VME_DMA_PCI: + pci_attr = dest->private; + + reg_split((unsigned long long)pci_attr->address, &address_high, + &address_low); + entry->descriptor.ddau = cpu_to_be32(address_high); + entry->descriptor.ddal = cpu_to_be32(address_low); + entry->descriptor.ddat = cpu_to_be32(TSI148_LCSR_DDAT_TYP_PCI); + break; + case VME_DMA_VME: + vme_attr = dest->private; + + reg_split((unsigned long long)vme_attr->address, &address_high, + &address_low); + entry->descriptor.ddau = cpu_to_be32(address_high); + entry->descriptor.ddal = cpu_to_be32(address_low); + entry->descriptor.ddat = cpu_to_be32(TSI148_LCSR_DDAT_TYP_VME); + + retval = tsi148_dma_set_vme_dest_attributes( + tsi148_bridge->parent, &entry->descriptor.ddat, + vme_attr->aspace, vme_attr->cycle, vme_attr->dwidth); + if (retval < 0) + goto err_dest; + break; + default: + dev_err(tsi148_bridge->parent, "Invalid destination type\n"); + retval = -EINVAL; + goto err_dest; + break; + } + + /* Fill out count */ + entry->descriptor.dcnt = cpu_to_be32((u32)count); + + /* Add to list */ + list_add_tail(&entry->list, &list->entries); + + /* Fill out previous descriptors "Next Address" */ + if (entry->list.prev != &list->entries) { + prev = list_entry(entry->list.prev, struct tsi148_dma_entry, + list); + /* We need the bus address for the pointer */ + entry->dma_handle = dma_map_single(tsi148_bridge->parent, + &entry->descriptor, + sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE); + + reg_split((unsigned long long)entry->dma_handle, &address_high, + &address_low); + entry->descriptor.dnlau = cpu_to_be32(address_high); + entry->descriptor.dnlal = cpu_to_be32(address_low); + + } + + return 0; + +err_dest: +err_source: +err_align: + kfree(entry); +err_mem: + return retval; +} + +/* + * Check to see if the provided DMA channel is busy. + */ +static int tsi148_dma_busy(struct vme_bridge *tsi148_bridge, int channel) +{ + u32 tmp; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + tmp = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + + TSI148_LCSR_OFFSET_DSTA); + + if (tmp & TSI148_LCSR_DSTA_BSY) + return 0; + else + return 1; + +} + +/* + * Execute a previously generated link list + * + * XXX Need to provide control register configuration. + */ +static int tsi148_dma_list_exec(struct vme_dma_list *list) +{ + struct vme_dma_resource *ctrlr; + int channel, retval = 0; + struct tsi148_dma_entry *entry; + u32 bus_addr_high, bus_addr_low; + u32 val, dctlreg = 0; + struct vme_bridge *tsi148_bridge; + struct tsi148_driver *bridge; + + ctrlr = list->parent; + + tsi148_bridge = ctrlr->parent; + + bridge = tsi148_bridge->driver_priv; + + mutex_lock(&ctrlr->mtx); + + channel = ctrlr->number; + + if (!list_empty(&ctrlr->running)) { + /* + * XXX We have an active DMA transfer and currently haven't + * sorted out the mechanism for "pending" DMA transfers. + * Return busy. + */ + /* Need to add to pending here */ + mutex_unlock(&ctrlr->mtx); + return -EBUSY; + } else { + list_add(&list->list, &ctrlr->running); + } + + /* Get first bus address and write into registers */ + entry = list_first_entry(&list->entries, struct tsi148_dma_entry, + list); + + entry->dma_handle = dma_map_single(tsi148_bridge->parent, + &entry->descriptor, + sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE); + + mutex_unlock(&ctrlr->mtx); + + reg_split(entry->dma_handle, &bus_addr_high, &bus_addr_low); + + iowrite32be(bus_addr_high, bridge->base + + TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU); + iowrite32be(bus_addr_low, bridge->base + + TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL); + + dctlreg = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + + TSI148_LCSR_OFFSET_DCTL); + + /* Start the operation */ + iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base + + TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL); + + wait_event_interruptible(bridge->dma_queue[channel], + tsi148_dma_busy(ctrlr->parent, channel)); + + /* + * Read status register, this register is valid until we kick off a + * new transfer. + */ + val = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] + + TSI148_LCSR_OFFSET_DSTA); + + if (val & TSI148_LCSR_DSTA_VBE) { + dev_err(tsi148_bridge->parent, "DMA Error. DSTA=%08X\n", val); + retval = -EIO; + } + + /* Remove list from running list */ + mutex_lock(&ctrlr->mtx); + list_del(&list->list); + mutex_unlock(&ctrlr->mtx); + + return retval; +} + +/* + * Clean up a previously generated link list + * + * We have a separate function, don't assume that the chain can't be reused. + */ +static int tsi148_dma_list_empty(struct vme_dma_list *list) +{ + struct list_head *pos, *temp; + struct tsi148_dma_entry *entry; + + struct vme_bridge *tsi148_bridge = list->parent->parent; + + /* detach and free each entry */ + list_for_each_safe(pos, temp, &list->entries) { + list_del(pos); + entry = list_entry(pos, struct tsi148_dma_entry, list); + + dma_unmap_single(tsi148_bridge->parent, entry->dma_handle, + sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE); + kfree(entry); + } + + return 0; +} + +/* + * All 4 location monitors reside at the same base - this is therefore a + * system wide configuration. + * + * This does not enable the LM monitor - that should be done when the first + * callback is attached and disabled when the last callback is removed. + */ +static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, + u32 aspace, u32 cycle) +{ + u32 lm_base_high, lm_base_low, lm_ctl = 0; + int i; + struct vme_bridge *tsi148_bridge; + struct tsi148_driver *bridge; + + tsi148_bridge = lm->parent; + + bridge = tsi148_bridge->driver_priv; + + mutex_lock(&lm->mtx); + + /* If we already have a callback attached, we can't move it! */ + for (i = 0; i < lm->monitors; i++) { + if (bridge->lm_callback[i] != NULL) { + mutex_unlock(&lm->mtx); + dev_err(tsi148_bridge->parent, "Location monitor " + "callback attached, can't reset\n"); + return -EBUSY; + } + } + + switch (aspace) { + case VME_A16: + lm_ctl |= TSI148_LCSR_LMAT_AS_A16; + break; + case VME_A24: + lm_ctl |= TSI148_LCSR_LMAT_AS_A24; + break; + case VME_A32: + lm_ctl |= TSI148_LCSR_LMAT_AS_A32; + break; + case VME_A64: + lm_ctl |= TSI148_LCSR_LMAT_AS_A64; + break; + default: + mutex_unlock(&lm->mtx); + dev_err(tsi148_bridge->parent, "Invalid address space\n"); + return -EINVAL; + break; + } + + if (cycle & VME_SUPER) + lm_ctl |= TSI148_LCSR_LMAT_SUPR ; + if (cycle & VME_USER) + lm_ctl |= TSI148_LCSR_LMAT_NPRIV; + if (cycle & VME_PROG) + lm_ctl |= TSI148_LCSR_LMAT_PGM; + if (cycle & VME_DATA) + lm_ctl |= TSI148_LCSR_LMAT_DATA; + + reg_split(lm_base, &lm_base_high, &lm_base_low); + + iowrite32be(lm_base_high, bridge->base + TSI148_LCSR_LMBAU); + iowrite32be(lm_base_low, bridge->base + TSI148_LCSR_LMBAL); + iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT); + + mutex_unlock(&lm->mtx); + + return 0; +} + +/* Get configuration of the callback monitor and return whether it is enabled + * or disabled. + */ +static int tsi148_lm_get(struct vme_lm_resource *lm, + unsigned long long *lm_base, u32 *aspace, u32 *cycle) +{ + u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0; + struct tsi148_driver *bridge; + + bridge = lm->parent->driver_priv; + + mutex_lock(&lm->mtx); + + lm_base_high = ioread32be(bridge->base + TSI148_LCSR_LMBAU); + lm_base_low = ioread32be(bridge->base + TSI148_LCSR_LMBAL); + lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT); + + reg_join(lm_base_high, lm_base_low, lm_base); + + if (lm_ctl & TSI148_LCSR_LMAT_EN) + enabled = 1; + + if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A16) + *aspace |= VME_A16; + + if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A24) + *aspace |= VME_A24; + + if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A32) + *aspace |= VME_A32; + + if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A64) + *aspace |= VME_A64; + + + if (lm_ctl & TSI148_LCSR_LMAT_SUPR) + *cycle |= VME_SUPER; + if (lm_ctl & TSI148_LCSR_LMAT_NPRIV) + *cycle |= VME_USER; + if (lm_ctl & TSI148_LCSR_LMAT_PGM) + *cycle |= VME_PROG; + if (lm_ctl & TSI148_LCSR_LMAT_DATA) + *cycle |= VME_DATA; + + mutex_unlock(&lm->mtx); + + return enabled; +} + +/* + * Attach a callback to a specific location monitor. + * + * Callback will be passed the monitor triggered. + */ +static int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor, + void (*callback)(int)) +{ + u32 lm_ctl, tmp; + struct vme_bridge *tsi148_bridge; + struct tsi148_driver *bridge; + + tsi148_bridge = lm->parent; + + bridge = tsi148_bridge->driver_priv; + + mutex_lock(&lm->mtx); + + /* Ensure that the location monitor is configured - need PGM or DATA */ + lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT); + if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) { + mutex_unlock(&lm->mtx); + dev_err(tsi148_bridge->parent, "Location monitor not properly " + "configured\n"); + return -EINVAL; + } + + /* Check that a callback isn't already attached */ + if (bridge->lm_callback[monitor] != NULL) { + mutex_unlock(&lm->mtx); + dev_err(tsi148_bridge->parent, "Existing callback attached\n"); + return -EBUSY; + } + + /* Attach callback */ + bridge->lm_callback[monitor] = callback; + + /* Enable Location Monitor interrupt */ + tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN); + tmp |= TSI148_LCSR_INTEN_LMEN[monitor]; + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN); + + tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); + tmp |= TSI148_LCSR_INTEO_LMEO[monitor]; + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); + + /* Ensure that global Location Monitor Enable set */ + if ((lm_ctl & TSI148_LCSR_LMAT_EN) == 0) { + lm_ctl |= TSI148_LCSR_LMAT_EN; + iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT); + } + + mutex_unlock(&lm->mtx); + + return 0; +} + +/* + * Detach a callback function forn a specific location monitor. + */ +static int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor) +{ + u32 lm_en, tmp; + struct tsi148_driver *bridge; + + bridge = lm->parent->driver_priv; + + mutex_lock(&lm->mtx); + + /* Disable Location Monitor and ensure previous interrupts are clear */ + lm_en = ioread32be(bridge->base + TSI148_LCSR_INTEN); + lm_en &= ~TSI148_LCSR_INTEN_LMEN[monitor]; + iowrite32be(lm_en, bridge->base + TSI148_LCSR_INTEN); + + tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO); + tmp &= ~TSI148_LCSR_INTEO_LMEO[monitor]; + iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); + + iowrite32be(TSI148_LCSR_INTC_LMC[monitor], + bridge->base + TSI148_LCSR_INTC); + + /* Detach callback */ + bridge->lm_callback[monitor] = NULL; + + /* If all location monitors disabled, disable global Location Monitor */ + if ((lm_en & (TSI148_LCSR_INTS_LM0S | TSI148_LCSR_INTS_LM1S | + TSI148_LCSR_INTS_LM2S | TSI148_LCSR_INTS_LM3S)) == 0) { + tmp = ioread32be(bridge->base + TSI148_LCSR_LMAT); + tmp &= ~TSI148_LCSR_LMAT_EN; + iowrite32be(tmp, bridge->base + TSI148_LCSR_LMAT); + } + + mutex_unlock(&lm->mtx); + + return 0; +} + +/* + * Determine Geographical Addressing + */ +static int tsi148_slot_get(struct vme_bridge *tsi148_bridge) +{ + u32 slot = 0; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + if (!geoid) { + slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT); + slot = slot & TSI148_LCSR_VSTAT_GA_M; + } else + slot = geoid; + + return (int)slot; +} + +void *tsi148_alloc_consistent(struct device *parent, size_t size, + dma_addr_t *dma) +{ + struct pci_dev *pdev; + + /* Find pci_dev container of dev */ + pdev = container_of(parent, struct pci_dev, dev); + + return pci_alloc_consistent(pdev, size, dma); +} + +void tsi148_free_consistent(struct device *parent, size_t size, void *vaddr, + dma_addr_t dma) +{ + struct pci_dev *pdev; + + /* Find pci_dev container of dev */ + pdev = container_of(parent, struct pci_dev, dev); + + pci_free_consistent(pdev, size, vaddr, dma); +} + +static int __init tsi148_init(void) +{ + return pci_register_driver(&tsi148_driver); +} + +/* + * Configure CR/CSR space + * + * Access to the CR/CSR can be configured at power-up. The location of the + * CR/CSR registers in the CR/CSR address space is determined by the boards + * Auto-ID or Geographic address. This function ensures that the window is + * enabled at an offset consistent with the boards geopgraphic address. + * + * Each board has a 512kB window, with the highest 4kB being used for the + * boards registers, this means there is a fix length 508kB window which must + * be mapped onto PCI memory. + */ +static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge, + struct pci_dev *pdev) +{ + u32 cbar, crat, vstat; + u32 crcsr_bus_high, crcsr_bus_low; + int retval; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + /* Allocate mem for CR/CSR image */ + bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, + &bridge->crcsr_bus); + if (bridge->crcsr_kernel == NULL) { + dev_err(tsi148_bridge->parent, "Failed to allocate memory for " + "CR/CSR image\n"); + return -ENOMEM; + } + + memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); + + reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low); + + iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU); + iowrite32be(crcsr_bus_low, bridge->base + TSI148_LCSR_CROL); + + /* Ensure that the CR/CSR is configured at the correct offset */ + cbar = ioread32be(bridge->base + TSI148_CBAR); + cbar = (cbar & TSI148_CRCSR_CBAR_M)>>3; + + vstat = tsi148_slot_get(tsi148_bridge); + + if (cbar != vstat) { + cbar = vstat; + dev_info(tsi148_bridge->parent, "Setting CR/CSR offset\n"); + iowrite32be(cbar<<3, bridge->base + TSI148_CBAR); + } + dev_info(tsi148_bridge->parent, "CR/CSR Offset: %d\n", cbar); + + crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); + if (crat & TSI148_LCSR_CRAT_EN) { + dev_info(tsi148_bridge->parent, "Enabling CR/CSR space\n"); + iowrite32be(crat | TSI148_LCSR_CRAT_EN, + bridge->base + TSI148_LCSR_CRAT); + } else + dev_info(tsi148_bridge->parent, "CR/CSR already enabled\n"); + + /* If we want flushed, error-checked writes, set up a window + * over the CR/CSR registers. We read from here to safely flush + * through VME writes. + */ + if (err_chk) { + retval = tsi148_master_set(bridge->flush_image, 1, + (vstat * 0x80000), 0x80000, VME_CRCSR, VME_SCT, + VME_D16); + if (retval) + dev_err(tsi148_bridge->parent, "Configuring flush image" + " failed\n"); + } + + return 0; + +} + +static void tsi148_crcsr_exit(struct vme_bridge *tsi148_bridge, + struct pci_dev *pdev) +{ + u32 crat; + struct tsi148_driver *bridge; + + bridge = tsi148_bridge->driver_priv; + + /* Turn off CR/CSR space */ + crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); + iowrite32be(crat & ~TSI148_LCSR_CRAT_EN, + bridge->base + TSI148_LCSR_CRAT); + + /* Free image */ + iowrite32be(0, bridge->base + TSI148_LCSR_CROU); + iowrite32be(0, bridge->base + TSI148_LCSR_CROL); + + pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel, + bridge->crcsr_bus); +} + +static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int retval, i, master_num; + u32 data; + struct list_head *pos = NULL; + struct vme_bridge *tsi148_bridge; + struct tsi148_driver *tsi148_device; + struct vme_master_resource *master_image; + struct vme_slave_resource *slave_image; + struct vme_dma_resource *dma_ctrlr; + struct vme_lm_resource *lm; + + /* If we want to support more than one of each bridge, we need to + * dynamically generate this so we get one per device + */ + tsi148_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); + if (tsi148_bridge == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for device " + "structure\n"); + retval = -ENOMEM; + goto err_struct; + } + + tsi148_device = kzalloc(sizeof(struct tsi148_driver), GFP_KERNEL); + if (tsi148_device == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for device " + "structure\n"); + retval = -ENOMEM; + goto err_driver; + } + + tsi148_bridge->driver_priv = tsi148_device; + + /* Enable the device */ + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "Unable to enable device\n"); + goto err_enable; + } + + /* Map Registers */ + retval = pci_request_regions(pdev, driver_name); + if (retval) { + dev_err(&pdev->dev, "Unable to reserve resources\n"); + goto err_resource; + } + + /* map registers in BAR 0 */ + tsi148_device->base = ioremap_nocache(pci_resource_start(pdev, 0), + 4096); + if (!tsi148_device->base) { + dev_err(&pdev->dev, "Unable to remap CRG region\n"); + retval = -EIO; + goto err_remap; + } + + /* Check to see if the mapping worked out */ + data = ioread32(tsi148_device->base + TSI148_PCFS_ID) & 0x0000FFFF; + if (data != PCI_VENDOR_ID_TUNDRA) { + dev_err(&pdev->dev, "CRG region check failed\n"); + retval = -EIO; + goto err_test; + } + + /* Initialize wait queues & mutual exclusion flags */ + init_waitqueue_head(&tsi148_device->dma_queue[0]); + init_waitqueue_head(&tsi148_device->dma_queue[1]); + init_waitqueue_head(&tsi148_device->iack_queue); + mutex_init(&tsi148_device->vme_int); + mutex_init(&tsi148_device->vme_rmw); + + tsi148_bridge->parent = &pdev->dev; + strcpy(tsi148_bridge->name, driver_name); + + /* Setup IRQ */ + retval = tsi148_irq_init(tsi148_bridge); + if (retval != 0) { + dev_err(&pdev->dev, "Chip Initialization failed.\n"); + goto err_irq; + } + + /* If we are going to flush writes, we need to read from the VME bus. + * We need to do this safely, thus we read the devices own CR/CSR + * register. To do this we must set up a window in CR/CSR space and + * hence have one less master window resource available. + */ + master_num = TSI148_MAX_MASTER; + if (err_chk) { + master_num--; + + tsi148_device->flush_image = + kmalloc(sizeof(struct vme_master_resource), GFP_KERNEL); + if (tsi148_device->flush_image == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "flush resource structure\n"); + retval = -ENOMEM; + goto err_master; + } + tsi148_device->flush_image->parent = tsi148_bridge; + spin_lock_init(&tsi148_device->flush_image->lock); + tsi148_device->flush_image->locked = 1; + tsi148_device->flush_image->number = master_num; + tsi148_device->flush_image->address_attr = VME_A16 | VME_A24 | + VME_A32 | VME_A64; + tsi148_device->flush_image->cycle_attr = VME_SCT | VME_BLT | + VME_MBLT | VME_2eVME | VME_2eSST | VME_2eSSTB | + VME_2eSST160 | VME_2eSST267 | VME_2eSST320 | VME_SUPER | + VME_USER | VME_PROG | VME_DATA; + tsi148_device->flush_image->width_attr = VME_D16 | VME_D32; + memset(&tsi148_device->flush_image->bus_resource, 0, + sizeof(struct resource)); + tsi148_device->flush_image->kern_base = NULL; + } + + /* Add master windows to list */ + INIT_LIST_HEAD(&tsi148_bridge->master_resources); + for (i = 0; i < master_num; i++) { + master_image = kmalloc(sizeof(struct vme_master_resource), + GFP_KERNEL); + if (master_image == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "master resource structure\n"); + retval = -ENOMEM; + goto err_master; + } + master_image->parent = tsi148_bridge; + spin_lock_init(&master_image->lock); + master_image->locked = 0; + master_image->number = i; + master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | + VME_A64; + master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | + VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 | + VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER | + VME_PROG | VME_DATA; + master_image->width_attr = VME_D16 | VME_D32; + memset(&master_image->bus_resource, 0, + sizeof(struct resource)); + master_image->kern_base = NULL; + list_add_tail(&master_image->list, + &tsi148_bridge->master_resources); + } + + /* Add slave windows to list */ + INIT_LIST_HEAD(&tsi148_bridge->slave_resources); + for (i = 0; i < TSI148_MAX_SLAVE; i++) { + slave_image = kmalloc(sizeof(struct vme_slave_resource), + GFP_KERNEL); + if (slave_image == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "slave resource structure\n"); + retval = -ENOMEM; + goto err_slave; + } + slave_image->parent = tsi148_bridge; + mutex_init(&slave_image->mtx); + slave_image->locked = 0; + slave_image->number = i; + slave_image->address_attr = VME_A16 | VME_A24 | VME_A32 | + VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 | + VME_USER3 | VME_USER4; + slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | + VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 | + VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER | + VME_PROG | VME_DATA; + list_add_tail(&slave_image->list, + &tsi148_bridge->slave_resources); + } + + /* Add dma engines to list */ + INIT_LIST_HEAD(&tsi148_bridge->dma_resources); + for (i = 0; i < TSI148_MAX_DMA; i++) { + dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), + GFP_KERNEL); + if (dma_ctrlr == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "dma resource structure\n"); + retval = -ENOMEM; + goto err_dma; + } + dma_ctrlr->parent = tsi148_bridge; + mutex_init(&dma_ctrlr->mtx); + dma_ctrlr->locked = 0; + dma_ctrlr->number = i; + dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM | + VME_DMA_MEM_TO_VME | VME_DMA_VME_TO_VME | + VME_DMA_MEM_TO_MEM | VME_DMA_PATTERN_TO_VME | + VME_DMA_PATTERN_TO_MEM; + INIT_LIST_HEAD(&dma_ctrlr->pending); + INIT_LIST_HEAD(&dma_ctrlr->running); + list_add_tail(&dma_ctrlr->list, + &tsi148_bridge->dma_resources); + } + + /* Add location monitor to list */ + INIT_LIST_HEAD(&tsi148_bridge->lm_resources); + lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); + if (lm == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory for " + "location monitor resource structure\n"); + retval = -ENOMEM; + goto err_lm; + } + lm->parent = tsi148_bridge; + mutex_init(&lm->mtx); + lm->locked = 0; + lm->number = 1; + lm->monitors = 4; + list_add_tail(&lm->list, &tsi148_bridge->lm_resources); + + tsi148_bridge->slave_get = tsi148_slave_get; + tsi148_bridge->slave_set = tsi148_slave_set; + tsi148_bridge->master_get = tsi148_master_get; + tsi148_bridge->master_set = tsi148_master_set; + tsi148_bridge->master_read = tsi148_master_read; + tsi148_bridge->master_write = tsi148_master_write; + tsi148_bridge->master_rmw = tsi148_master_rmw; + tsi148_bridge->dma_list_add = tsi148_dma_list_add; + tsi148_bridge->dma_list_exec = tsi148_dma_list_exec; + tsi148_bridge->dma_list_empty = tsi148_dma_list_empty; + tsi148_bridge->irq_set = tsi148_irq_set; + tsi148_bridge->irq_generate = tsi148_irq_generate; + tsi148_bridge->lm_set = tsi148_lm_set; + tsi148_bridge->lm_get = tsi148_lm_get; + tsi148_bridge->lm_attach = tsi148_lm_attach; + tsi148_bridge->lm_detach = tsi148_lm_detach; + tsi148_bridge->slot_get = tsi148_slot_get; + tsi148_bridge->alloc_consistent = tsi148_alloc_consistent; + tsi148_bridge->free_consistent = tsi148_free_consistent; + + data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); + dev_info(&pdev->dev, "Board is%s the VME system controller\n", + (data & TSI148_LCSR_VSTAT_SCONS) ? "" : " not"); + if (!geoid) + dev_info(&pdev->dev, "VME geographical address is %d\n", + data & TSI148_LCSR_VSTAT_GA_M); + else + dev_info(&pdev->dev, "VME geographical address is set to %d\n", + geoid); + + dev_info(&pdev->dev, "VME Write and flush and error check is %s\n", + err_chk ? "enabled" : "disabled"); + + if (tsi148_crcsr_init(tsi148_bridge, pdev)) { + dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); + goto err_crcsr; + } + + retval = vme_register_bridge(tsi148_bridge); + if (retval != 0) { + dev_err(&pdev->dev, "Chip Registration failed.\n"); + goto err_reg; + } + + pci_set_drvdata(pdev, tsi148_bridge); + + /* Clear VME bus "board fail", and "power-up reset" lines */ + data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT); + data &= ~TSI148_LCSR_VSTAT_BRDFL; + data |= TSI148_LCSR_VSTAT_CPURST; + iowrite32be(data, tsi148_device->base + TSI148_LCSR_VSTAT); + + return 0; + +err_reg: + tsi148_crcsr_exit(tsi148_bridge, pdev); +err_crcsr: +err_lm: + /* resources are stored in link list */ + list_for_each(pos, &tsi148_bridge->lm_resources) { + lm = list_entry(pos, struct vme_lm_resource, list); + list_del(pos); + kfree(lm); + } +err_dma: + /* resources are stored in link list */ + list_for_each(pos, &tsi148_bridge->dma_resources) { + dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); + list_del(pos); + kfree(dma_ctrlr); + } +err_slave: + /* resources are stored in link list */ + list_for_each(pos, &tsi148_bridge->slave_resources) { + slave_image = list_entry(pos, struct vme_slave_resource, list); + list_del(pos); + kfree(slave_image); + } +err_master: + /* resources are stored in link list */ + list_for_each(pos, &tsi148_bridge->master_resources) { + master_image = list_entry(pos, struct vme_master_resource, + list); + list_del(pos); + kfree(master_image); + } + + tsi148_irq_exit(tsi148_bridge, pdev); +err_irq: +err_test: + iounmap(tsi148_device->base); +err_remap: + pci_release_regions(pdev); +err_resource: + pci_disable_device(pdev); +err_enable: + kfree(tsi148_device); +err_driver: + kfree(tsi148_bridge); +err_struct: + return retval; + +} + +static void tsi148_remove(struct pci_dev *pdev) +{ + struct list_head *pos = NULL; + struct list_head *tmplist; + struct vme_master_resource *master_image; + struct vme_slave_resource *slave_image; + struct vme_dma_resource *dma_ctrlr; + int i; + struct tsi148_driver *bridge; + struct vme_bridge *tsi148_bridge = pci_get_drvdata(pdev); + + bridge = tsi148_bridge->driver_priv; + + + dev_dbg(&pdev->dev, "Driver is being unloaded.\n"); + + /* + * Shutdown all inbound and outbound windows. + */ + for (i = 0; i < 8; i++) { + iowrite32be(0, bridge->base + TSI148_LCSR_IT[i] + + TSI148_LCSR_OFFSET_ITAT); + iowrite32be(0, bridge->base + TSI148_LCSR_OT[i] + + TSI148_LCSR_OFFSET_OTAT); + } + + /* + * Shutdown Location monitor. + */ + iowrite32be(0, bridge->base + TSI148_LCSR_LMAT); + + /* + * Shutdown CRG map. + */ + iowrite32be(0, bridge->base + TSI148_LCSR_CSRAT); + + /* + * Clear error status. + */ + iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_EDPAT); + iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_VEAT); + iowrite32be(0x07000700, bridge->base + TSI148_LCSR_PSTAT); + + /* + * Remove VIRQ interrupt (if any) + */ + if (ioread32be(bridge->base + TSI148_LCSR_VICR) & 0x800) + iowrite32be(0x8000, bridge->base + TSI148_LCSR_VICR); + + /* + * Map all Interrupts to PCI INTA + */ + iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM1); + iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM2); + + tsi148_irq_exit(tsi148_bridge, pdev); + + vme_unregister_bridge(tsi148_bridge); + + tsi148_crcsr_exit(tsi148_bridge, pdev); + + /* resources are stored in link list */ + list_for_each_safe(pos, tmplist, &tsi148_bridge->dma_resources) { + dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); + list_del(pos); + kfree(dma_ctrlr); + } + + /* resources are stored in link list */ + list_for_each_safe(pos, tmplist, &tsi148_bridge->slave_resources) { + slave_image = list_entry(pos, struct vme_slave_resource, list); + list_del(pos); + kfree(slave_image); + } + + /* resources are stored in link list */ + list_for_each_safe(pos, tmplist, &tsi148_bridge->master_resources) { + master_image = list_entry(pos, struct vme_master_resource, + list); + list_del(pos); + kfree(master_image); + } + + iounmap(bridge->base); + + pci_release_regions(pdev); + + pci_disable_device(pdev); + + kfree(tsi148_bridge->driver_priv); + + kfree(tsi148_bridge); +} + +static void __exit tsi148_exit(void) +{ + pci_unregister_driver(&tsi148_driver); +} + +MODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes"); +module_param(err_chk, bool, 0); + +MODULE_PARM_DESC(geoid, "Override geographical addressing"); +module_param(geoid, int, 0); + +MODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge"); +MODULE_LICENSE("GPL"); + +module_init(tsi148_init); +module_exit(tsi148_exit); diff --git a/drivers/vme/bridges/vme_tsi148.h b/drivers/vme/bridges/vme_tsi148.h new file mode 100644 index 000000000000..f5ed14382a8d --- /dev/null +++ b/drivers/vme/bridges/vme_tsi148.h @@ -0,0 +1,1410 @@ +/* + * tsi148.h + * + * Support for the Tundra TSI148 VME Bridge chip + * + * Author: Tom Armistead + * Updated and maintained by Ajit Prem + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef TSI148_H +#define TSI148_H + +#ifndef PCI_VENDOR_ID_TUNDRA +#define PCI_VENDOR_ID_TUNDRA 0x10e3 +#endif + +#ifndef PCI_DEVICE_ID_TUNDRA_TSI148 +#define PCI_DEVICE_ID_TUNDRA_TSI148 0x148 +#endif + +/* + * Define the number of each that the Tsi148 supports. + */ +#define TSI148_MAX_MASTER 8 /* Max Master Windows */ +#define TSI148_MAX_SLAVE 8 /* Max Slave Windows */ +#define TSI148_MAX_DMA 2 /* Max DMA Controllers */ +#define TSI148_MAX_MAILBOX 4 /* Max Mail Box registers */ +#define TSI148_MAX_SEMAPHORE 8 /* Max Semaphores */ + +/* Structure used to hold driver specific information */ +struct tsi148_driver { + void __iomem *base; /* Base Address of device registers */ + wait_queue_head_t dma_queue[2]; + wait_queue_head_t iack_queue; + void (*lm_callback[4])(int); /* Called in interrupt handler */ + void *crcsr_kernel; + dma_addr_t crcsr_bus; + struct vme_master_resource *flush_image; + struct mutex vme_rmw; /* Only one RMW cycle at a time */ + struct mutex vme_int; /* + * Only one VME interrupt can be + * generated at a time, provide locking + */ +}; + +/* + * Layout of a DMAC Linked-List Descriptor + * + * Note: This structure is accessed via the chip and therefore must be + * correctly laid out - It must also be aligned on 64-bit boundaries. + */ +struct tsi148_dma_descriptor { + __be32 dsau; /* Source Address */ + __be32 dsal; + __be32 ddau; /* Destination Address */ + __be32 ddal; + __be32 dsat; /* Source attributes */ + __be32 ddat; /* Destination attributes */ + __be32 dnlau; /* Next link address */ + __be32 dnlal; + __be32 dcnt; /* Byte count */ + __be32 ddbs; /* 2eSST Broadcast select */ +}; + +struct tsi148_dma_entry { + /* + * The descriptor needs to be aligned on a 64-bit boundary, we increase + * the chance of this by putting it first in the structure. + */ + struct tsi148_dma_descriptor descriptor; + struct list_head list; + dma_addr_t dma_handle; +}; + +/* + * TSI148 ASIC register structure overlays and bit field definitions. + * + * Note: Tsi148 Register Group (CRG) consists of the following + * combination of registers: + * PCFS - PCI Configuration Space Registers + * LCSR - Local Control and Status Registers + * GCSR - Global Control and Status Registers + * CR/CSR - Subset of Configuration ROM / + * Control and Status Registers + */ + + +/* + * Command/Status Registers (CRG + $004) + */ +#define TSI148_PCFS_ID 0x0 +#define TSI148_PCFS_CSR 0x4 +#define TSI148_PCFS_CLASS 0x8 +#define TSI148_PCFS_MISC0 0xC +#define TSI148_PCFS_MBARL 0x10 +#define TSI148_PCFS_MBARU 0x14 + +#define TSI148_PCFS_SUBID 0x28 + +#define TSI148_PCFS_CAPP 0x34 + +#define TSI148_PCFS_MISC1 0x3C + +#define TSI148_PCFS_XCAPP 0x40 +#define TSI148_PCFS_XSTAT 0x44 + +/* + * LCSR definitions + */ + +/* + * Outbound Translations + */ +#define TSI148_LCSR_OT0_OTSAU 0x100 +#define TSI148_LCSR_OT0_OTSAL 0x104 +#define TSI148_LCSR_OT0_OTEAU 0x108 +#define TSI148_LCSR_OT0_OTEAL 0x10C +#define TSI148_LCSR_OT0_OTOFU 0x110 +#define TSI148_LCSR_OT0_OTOFL 0x114 +#define TSI148_LCSR_OT0_OTBS 0x118 +#define TSI148_LCSR_OT0_OTAT 0x11C + +#define TSI148_LCSR_OT1_OTSAU 0x120 +#define TSI148_LCSR_OT1_OTSAL 0x124 +#define TSI148_LCSR_OT1_OTEAU 0x128 +#define TSI148_LCSR_OT1_OTEAL 0x12C +#define TSI148_LCSR_OT1_OTOFU 0x130 +#define TSI148_LCSR_OT1_OTOFL 0x134 +#define TSI148_LCSR_OT1_OTBS 0x138 +#define TSI148_LCSR_OT1_OTAT 0x13C + +#define TSI148_LCSR_OT2_OTSAU 0x140 +#define TSI148_LCSR_OT2_OTSAL 0x144 +#define TSI148_LCSR_OT2_OTEAU 0x148 +#define TSI148_LCSR_OT2_OTEAL 0x14C +#define TSI148_LCSR_OT2_OTOFU 0x150 +#define TSI148_LCSR_OT2_OTOFL 0x154 +#define TSI148_LCSR_OT2_OTBS 0x158 +#define TSI148_LCSR_OT2_OTAT 0x15C + +#define TSI148_LCSR_OT3_OTSAU 0x160 +#define TSI148_LCSR_OT3_OTSAL 0x164 +#define TSI148_LCSR_OT3_OTEAU 0x168 +#define TSI148_LCSR_OT3_OTEAL 0x16C +#define TSI148_LCSR_OT3_OTOFU 0x170 +#define TSI148_LCSR_OT3_OTOFL 0x174 +#define TSI148_LCSR_OT3_OTBS 0x178 +#define TSI148_LCSR_OT3_OTAT 0x17C + +#define TSI148_LCSR_OT4_OTSAU 0x180 +#define TSI148_LCSR_OT4_OTSAL 0x184 +#define TSI148_LCSR_OT4_OTEAU 0x188 +#define TSI148_LCSR_OT4_OTEAL 0x18C +#define TSI148_LCSR_OT4_OTOFU 0x190 +#define TSI148_LCSR_OT4_OTOFL 0x194 +#define TSI148_LCSR_OT4_OTBS 0x198 +#define TSI148_LCSR_OT4_OTAT 0x19C + +#define TSI148_LCSR_OT5_OTSAU 0x1A0 +#define TSI148_LCSR_OT5_OTSAL 0x1A4 +#define TSI148_LCSR_OT5_OTEAU 0x1A8 +#define TSI148_LCSR_OT5_OTEAL 0x1AC +#define TSI148_LCSR_OT5_OTOFU 0x1B0 +#define TSI148_LCSR_OT5_OTOFL 0x1B4 +#define TSI148_LCSR_OT5_OTBS 0x1B8 +#define TSI148_LCSR_OT5_OTAT 0x1BC + +#define TSI148_LCSR_OT6_OTSAU 0x1C0 +#define TSI148_LCSR_OT6_OTSAL 0x1C4 +#define TSI148_LCSR_OT6_OTEAU 0x1C8 +#define TSI148_LCSR_OT6_OTEAL 0x1CC +#define TSI148_LCSR_OT6_OTOFU 0x1D0 +#define TSI148_LCSR_OT6_OTOFL 0x1D4 +#define TSI148_LCSR_OT6_OTBS 0x1D8 +#define TSI148_LCSR_OT6_OTAT 0x1DC + +#define TSI148_LCSR_OT7_OTSAU 0x1E0 +#define TSI148_LCSR_OT7_OTSAL 0x1E4 +#define TSI148_LCSR_OT7_OTEAU 0x1E8 +#define TSI148_LCSR_OT7_OTEAL 0x1EC +#define TSI148_LCSR_OT7_OTOFU 0x1F0 +#define TSI148_LCSR_OT7_OTOFL 0x1F4 +#define TSI148_LCSR_OT7_OTBS 0x1F8 +#define TSI148_LCSR_OT7_OTAT 0x1FC + +#define TSI148_LCSR_OT0 0x100 +#define TSI148_LCSR_OT1 0x120 +#define TSI148_LCSR_OT2 0x140 +#define TSI148_LCSR_OT3 0x160 +#define TSI148_LCSR_OT4 0x180 +#define TSI148_LCSR_OT5 0x1A0 +#define TSI148_LCSR_OT6 0x1C0 +#define TSI148_LCSR_OT7 0x1E0 + +static const int TSI148_LCSR_OT[8] = { TSI148_LCSR_OT0, TSI148_LCSR_OT1, + TSI148_LCSR_OT2, TSI148_LCSR_OT3, + TSI148_LCSR_OT4, TSI148_LCSR_OT5, + TSI148_LCSR_OT6, TSI148_LCSR_OT7 }; + +#define TSI148_LCSR_OFFSET_OTSAU 0x0 +#define TSI148_LCSR_OFFSET_OTSAL 0x4 +#define TSI148_LCSR_OFFSET_OTEAU 0x8 +#define TSI148_LCSR_OFFSET_OTEAL 0xC +#define TSI148_LCSR_OFFSET_OTOFU 0x10 +#define TSI148_LCSR_OFFSET_OTOFL 0x14 +#define TSI148_LCSR_OFFSET_OTBS 0x18 +#define TSI148_LCSR_OFFSET_OTAT 0x1C + +/* + * VMEbus interrupt ack + * offset 200 + */ +#define TSI148_LCSR_VIACK1 0x204 +#define TSI148_LCSR_VIACK2 0x208 +#define TSI148_LCSR_VIACK3 0x20C +#define TSI148_LCSR_VIACK4 0x210 +#define TSI148_LCSR_VIACK5 0x214 +#define TSI148_LCSR_VIACK6 0x218 +#define TSI148_LCSR_VIACK7 0x21C + +static const int TSI148_LCSR_VIACK[8] = { 0, TSI148_LCSR_VIACK1, + TSI148_LCSR_VIACK2, TSI148_LCSR_VIACK3, + TSI148_LCSR_VIACK4, TSI148_LCSR_VIACK5, + TSI148_LCSR_VIACK6, TSI148_LCSR_VIACK7 }; + +/* + * RMW + * offset 220 + */ +#define TSI148_LCSR_RMWAU 0x220 +#define TSI148_LCSR_RMWAL 0x224 +#define TSI148_LCSR_RMWEN 0x228 +#define TSI148_LCSR_RMWC 0x22C +#define TSI148_LCSR_RMWS 0x230 + +/* + * VMEbus control + * offset 234 + */ +#define TSI148_LCSR_VMCTRL 0x234 +#define TSI148_LCSR_VCTRL 0x238 +#define TSI148_LCSR_VSTAT 0x23C + +/* + * PCI status + * offset 240 + */ +#define TSI148_LCSR_PSTAT 0x240 + +/* + * VME filter. + * offset 250 + */ +#define TSI148_LCSR_VMEFL 0x250 + + /* + * VME exception. + * offset 260 + */ +#define TSI148_LCSR_VEAU 0x260 +#define TSI148_LCSR_VEAL 0x264 +#define TSI148_LCSR_VEAT 0x268 + + /* + * PCI error + * offset 270 + */ +#define TSI148_LCSR_EDPAU 0x270 +#define TSI148_LCSR_EDPAL 0x274 +#define TSI148_LCSR_EDPXA 0x278 +#define TSI148_LCSR_EDPXS 0x27C +#define TSI148_LCSR_EDPAT 0x280 + + /* + * Inbound Translations + * offset 300 + */ +#define TSI148_LCSR_IT0_ITSAU 0x300 +#define TSI148_LCSR_IT0_ITSAL 0x304 +#define TSI148_LCSR_IT0_ITEAU 0x308 +#define TSI148_LCSR_IT0_ITEAL 0x30C +#define TSI148_LCSR_IT0_ITOFU 0x310 +#define TSI148_LCSR_IT0_ITOFL 0x314 +#define TSI148_LCSR_IT0_ITAT 0x318 + +#define TSI148_LCSR_IT1_ITSAU 0x320 +#define TSI148_LCSR_IT1_ITSAL 0x324 +#define TSI148_LCSR_IT1_ITEAU 0x328 +#define TSI148_LCSR_IT1_ITEAL 0x32C +#define TSI148_LCSR_IT1_ITOFU 0x330 +#define TSI148_LCSR_IT1_ITOFL 0x334 +#define TSI148_LCSR_IT1_ITAT 0x338 + +#define TSI148_LCSR_IT2_ITSAU 0x340 +#define TSI148_LCSR_IT2_ITSAL 0x344 +#define TSI148_LCSR_IT2_ITEAU 0x348 +#define TSI148_LCSR_IT2_ITEAL 0x34C +#define TSI148_LCSR_IT2_ITOFU 0x350 +#define TSI148_LCSR_IT2_ITOFL 0x354 +#define TSI148_LCSR_IT2_ITAT 0x358 + +#define TSI148_LCSR_IT3_ITSAU 0x360 +#define TSI148_LCSR_IT3_ITSAL 0x364 +#define TSI148_LCSR_IT3_ITEAU 0x368 +#define TSI148_LCSR_IT3_ITEAL 0x36C +#define TSI148_LCSR_IT3_ITOFU 0x370 +#define TSI148_LCSR_IT3_ITOFL 0x374 +#define TSI148_LCSR_IT3_ITAT 0x378 + +#define TSI148_LCSR_IT4_ITSAU 0x380 +#define TSI148_LCSR_IT4_ITSAL 0x384 +#define TSI148_LCSR_IT4_ITEAU 0x388 +#define TSI148_LCSR_IT4_ITEAL 0x38C +#define TSI148_LCSR_IT4_ITOFU 0x390 +#define TSI148_LCSR_IT4_ITOFL 0x394 +#define TSI148_LCSR_IT4_ITAT 0x398 + +#define TSI148_LCSR_IT5_ITSAU 0x3A0 +#define TSI148_LCSR_IT5_ITSAL 0x3A4 +#define TSI148_LCSR_IT5_ITEAU 0x3A8 +#define TSI148_LCSR_IT5_ITEAL 0x3AC +#define TSI148_LCSR_IT5_ITOFU 0x3B0 +#define TSI148_LCSR_IT5_ITOFL 0x3B4 +#define TSI148_LCSR_IT5_ITAT 0x3B8 + +#define TSI148_LCSR_IT6_ITSAU 0x3C0 +#define TSI148_LCSR_IT6_ITSAL 0x3C4 +#define TSI148_LCSR_IT6_ITEAU 0x3C8 +#define TSI148_LCSR_IT6_ITEAL 0x3CC +#define TSI148_LCSR_IT6_ITOFU 0x3D0 +#define TSI148_LCSR_IT6_ITOFL 0x3D4 +#define TSI148_LCSR_IT6_ITAT 0x3D8 + +#define TSI148_LCSR_IT7_ITSAU 0x3E0 +#define TSI148_LCSR_IT7_ITSAL 0x3E4 +#define TSI148_LCSR_IT7_ITEAU 0x3E8 +#define TSI148_LCSR_IT7_ITEAL 0x3EC +#define TSI148_LCSR_IT7_ITOFU 0x3F0 +#define TSI148_LCSR_IT7_ITOFL 0x3F4 +#define TSI148_LCSR_IT7_ITAT 0x3F8 + + +#define TSI148_LCSR_IT0 0x300 +#define TSI148_LCSR_IT1 0x320 +#define TSI148_LCSR_IT2 0x340 +#define TSI148_LCSR_IT3 0x360 +#define TSI148_LCSR_IT4 0x380 +#define TSI148_LCSR_IT5 0x3A0 +#define TSI148_LCSR_IT6 0x3C0 +#define TSI148_LCSR_IT7 0x3E0 + +static const int TSI148_LCSR_IT[8] = { TSI148_LCSR_IT0, TSI148_LCSR_IT1, + TSI148_LCSR_IT2, TSI148_LCSR_IT3, + TSI148_LCSR_IT4, TSI148_LCSR_IT5, + TSI148_LCSR_IT6, TSI148_LCSR_IT7 }; + +#define TSI148_LCSR_OFFSET_ITSAU 0x0 +#define TSI148_LCSR_OFFSET_ITSAL 0x4 +#define TSI148_LCSR_OFFSET_ITEAU 0x8 +#define TSI148_LCSR_OFFSET_ITEAL 0xC +#define TSI148_LCSR_OFFSET_ITOFU 0x10 +#define TSI148_LCSR_OFFSET_ITOFL 0x14 +#define TSI148_LCSR_OFFSET_ITAT 0x18 + + /* + * Inbound Translation GCSR + * offset 400 + */ +#define TSI148_LCSR_GBAU 0x400 +#define TSI148_LCSR_GBAL 0x404 +#define TSI148_LCSR_GCSRAT 0x408 + + /* + * Inbound Translation CRG + * offset 40C + */ +#define TSI148_LCSR_CBAU 0x40C +#define TSI148_LCSR_CBAL 0x410 +#define TSI148_LCSR_CSRAT 0x414 + + /* + * Inbound Translation CR/CSR + * CRG + * offset 418 + */ +#define TSI148_LCSR_CROU 0x418 +#define TSI148_LCSR_CROL 0x41C +#define TSI148_LCSR_CRAT 0x420 + + /* + * Inbound Translation Location Monitor + * offset 424 + */ +#define TSI148_LCSR_LMBAU 0x424 +#define TSI148_LCSR_LMBAL 0x428 +#define TSI148_LCSR_LMAT 0x42C + + /* + * VMEbus Interrupt Control. + * offset 430 + */ +#define TSI148_LCSR_BCU 0x430 +#define TSI148_LCSR_BCL 0x434 +#define TSI148_LCSR_BPGTR 0x438 +#define TSI148_LCSR_BPCTR 0x43C +#define TSI148_LCSR_VICR 0x440 + + /* + * Local Bus Interrupt Control. + * offset 448 + */ +#define TSI148_LCSR_INTEN 0x448 +#define TSI148_LCSR_INTEO 0x44C +#define TSI148_LCSR_INTS 0x450 +#define TSI148_LCSR_INTC 0x454 +#define TSI148_LCSR_INTM1 0x458 +#define TSI148_LCSR_INTM2 0x45C + + /* + * DMA Controllers + * offset 500 + */ +#define TSI148_LCSR_DCTL0 0x500 +#define TSI148_LCSR_DSTA0 0x504 +#define TSI148_LCSR_DCSAU0 0x508 +#define TSI148_LCSR_DCSAL0 0x50C +#define TSI148_LCSR_DCDAU0 0x510 +#define TSI148_LCSR_DCDAL0 0x514 +#define TSI148_LCSR_DCLAU0 0x518 +#define TSI148_LCSR_DCLAL0 0x51C +#define TSI148_LCSR_DSAU0 0x520 +#define TSI148_LCSR_DSAL0 0x524 +#define TSI148_LCSR_DDAU0 0x528 +#define TSI148_LCSR_DDAL0 0x52C +#define TSI148_LCSR_DSAT0 0x530 +#define TSI148_LCSR_DDAT0 0x534 +#define TSI148_LCSR_DNLAU0 0x538 +#define TSI148_LCSR_DNLAL0 0x53C +#define TSI148_LCSR_DCNT0 0x540 +#define TSI148_LCSR_DDBS0 0x544 + +#define TSI148_LCSR_DCTL1 0x580 +#define TSI148_LCSR_DSTA1 0x584 +#define TSI148_LCSR_DCSAU1 0x588 +#define TSI148_LCSR_DCSAL1 0x58C +#define TSI148_LCSR_DCDAU1 0x590 +#define TSI148_LCSR_DCDAL1 0x594 +#define TSI148_LCSR_DCLAU1 0x598 +#define TSI148_LCSR_DCLAL1 0x59C +#define TSI148_LCSR_DSAU1 0x5A0 +#define TSI148_LCSR_DSAL1 0x5A4 +#define TSI148_LCSR_DDAU1 0x5A8 +#define TSI148_LCSR_DDAL1 0x5AC +#define TSI148_LCSR_DSAT1 0x5B0 +#define TSI148_LCSR_DDAT1 0x5B4 +#define TSI148_LCSR_DNLAU1 0x5B8 +#define TSI148_LCSR_DNLAL1 0x5BC +#define TSI148_LCSR_DCNT1 0x5C0 +#define TSI148_LCSR_DDBS1 0x5C4 + +#define TSI148_LCSR_DMA0 0x500 +#define TSI148_LCSR_DMA1 0x580 + + +static const int TSI148_LCSR_DMA[TSI148_MAX_DMA] = { TSI148_LCSR_DMA0, + TSI148_LCSR_DMA1 }; + +#define TSI148_LCSR_OFFSET_DCTL 0x0 +#define TSI148_LCSR_OFFSET_DSTA 0x4 +#define TSI148_LCSR_OFFSET_DCSAU 0x8 +#define TSI148_LCSR_OFFSET_DCSAL 0xC +#define TSI148_LCSR_OFFSET_DCDAU 0x10 +#define TSI148_LCSR_OFFSET_DCDAL 0x14 +#define TSI148_LCSR_OFFSET_DCLAU 0x18 +#define TSI148_LCSR_OFFSET_DCLAL 0x1C +#define TSI148_LCSR_OFFSET_DSAU 0x20 +#define TSI148_LCSR_OFFSET_DSAL 0x24 +#define TSI148_LCSR_OFFSET_DDAU 0x28 +#define TSI148_LCSR_OFFSET_DDAL 0x2C +#define TSI148_LCSR_OFFSET_DSAT 0x30 +#define TSI148_LCSR_OFFSET_DDAT 0x34 +#define TSI148_LCSR_OFFSET_DNLAU 0x38 +#define TSI148_LCSR_OFFSET_DNLAL 0x3C +#define TSI148_LCSR_OFFSET_DCNT 0x40 +#define TSI148_LCSR_OFFSET_DDBS 0x44 + + /* + * GCSR Register Group + */ + + /* + * GCSR CRG + * offset 00 600 - DEVI/VENI + * offset 04 604 - CTRL/GA/REVID + * offset 08 608 - Semaphore3/2/1/0 + * offset 0C 60C - Seamphore7/6/5/4 + */ +#define TSI148_GCSR_ID 0x600 +#define TSI148_GCSR_CSR 0x604 +#define TSI148_GCSR_SEMA0 0x608 +#define TSI148_GCSR_SEMA1 0x60C + + /* + * Mail Box + * GCSR CRG + * offset 10 610 - Mailbox0 + */ +#define TSI148_GCSR_MBOX0 0x610 +#define TSI148_GCSR_MBOX1 0x614 +#define TSI148_GCSR_MBOX2 0x618 +#define TSI148_GCSR_MBOX3 0x61C + +static const int TSI148_GCSR_MBOX[4] = { TSI148_GCSR_MBOX0, + TSI148_GCSR_MBOX1, + TSI148_GCSR_MBOX2, + TSI148_GCSR_MBOX3 }; + + /* + * CR/CSR + */ + + /* + * CR/CSR CRG + * offset 7FFF4 FF4 - CSRBCR + * offset 7FFF8 FF8 - CSRBSR + * offset 7FFFC FFC - CBAR + */ +#define TSI148_CSRBCR 0xFF4 +#define TSI148_CSRBSR 0xFF8 +#define TSI148_CBAR 0xFFC + + + + + /* + * TSI148 Register Bit Definitions + */ + + /* + * PFCS Register Set + */ +#define TSI148_PCFS_CMMD_SERR (1<<8) /* SERR_L out pin ssys err */ +#define TSI148_PCFS_CMMD_PERR (1<<6) /* PERR_L out pin parity */ +#define TSI148_PCFS_CMMD_MSTR (1<<2) /* PCI bus master */ +#define TSI148_PCFS_CMMD_MEMSP (1<<1) /* PCI mem space access */ +#define TSI148_PCFS_CMMD_IOSP (1<<0) /* PCI I/O space enable */ + +#define TSI148_PCFS_STAT_RCPVE (1<<15) /* Detected Parity Error */ +#define TSI148_PCFS_STAT_SIGSE (1<<14) /* Signalled System Error */ +#define TSI148_PCFS_STAT_RCVMA (1<<13) /* Received Master Abort */ +#define TSI148_PCFS_STAT_RCVTA (1<<12) /* Received Target Abort */ +#define TSI148_PCFS_STAT_SIGTA (1<<11) /* Signalled Target Abort */ +#define TSI148_PCFS_STAT_SELTIM (3<<9) /* DELSEL Timing */ +#define TSI148_PCFS_STAT_DPAR (1<<8) /* Data Parity Err Reported */ +#define TSI148_PCFS_STAT_FAST (1<<7) /* Fast back-to-back Cap */ +#define TSI148_PCFS_STAT_P66M (1<<5) /* 66 MHz Capable */ +#define TSI148_PCFS_STAT_CAPL (1<<4) /* Capab List - address $34 */ + +/* + * Revision ID/Class Code Registers (CRG +$008) + */ +#define TSI148_PCFS_CLAS_M (0xFF<<24) /* Class ID */ +#define TSI148_PCFS_SUBCLAS_M (0xFF<<16) /* Sub-Class ID */ +#define TSI148_PCFS_PROGIF_M (0xFF<<8) /* Sub-Class ID */ +#define TSI148_PCFS_REVID_M (0xFF<<0) /* Rev ID */ + +/* + * Cache Line Size/ Master Latency Timer/ Header Type Registers (CRG + $00C) + */ +#define TSI148_PCFS_HEAD_M (0xFF<<16) /* Master Lat Timer */ +#define TSI148_PCFS_MLAT_M (0xFF<<8) /* Master Lat Timer */ +#define TSI148_PCFS_CLSZ_M (0xFF<<0) /* Cache Line Size */ + +/* + * Memory Base Address Lower Reg (CRG + $010) + */ +#define TSI148_PCFS_MBARL_BASEL_M (0xFFFFF<<12) /* Base Addr Lower Mask */ +#define TSI148_PCFS_MBARL_PRE (1<<3) /* Prefetch */ +#define TSI148_PCFS_MBARL_MTYPE_M (3<<1) /* Memory Type Mask */ +#define TSI148_PCFS_MBARL_IOMEM (1<<0) /* I/O Space Indicator */ + +/* + * Message Signaled Interrupt Capabilities Register (CRG + $040) + */ +#define TSI148_PCFS_MSICAP_64BAC (1<<7) /* 64-bit Address Capable */ +#define TSI148_PCFS_MSICAP_MME_M (7<<4) /* Multiple Msg Enable Mask */ +#define TSI148_PCFS_MSICAP_MMC_M (7<<1) /* Multiple Msg Capable Mask */ +#define TSI148_PCFS_MSICAP_MSIEN (1<<0) /* Msg signaled INT Enable */ + +/* + * Message Address Lower Register (CRG +$044) + */ +#define TSI148_PCFS_MSIAL_M (0x3FFFFFFF<<2) /* Mask */ + +/* + * Message Data Register (CRG + 4C) + */ +#define TSI148_PCFS_MSIMD_M (0xFFFF<<0) /* Mask */ + +/* + * PCI-X Capabilities Register (CRG + $050) + */ +#define TSI148_PCFS_PCIXCAP_MOST_M (7<<4) /* Max outstanding Split Tran */ +#define TSI148_PCFS_PCIXCAP_MMRBC_M (3<<2) /* Max Mem Read byte cnt */ +#define TSI148_PCFS_PCIXCAP_ERO (1<<1) /* Enable Relaxed Ordering */ +#define TSI148_PCFS_PCIXCAP_DPERE (1<<0) /* Data Parity Recover Enable */ + +/* + * PCI-X Status Register (CRG +$054) + */ +#define TSI148_PCFS_PCIXSTAT_RSCEM (1<<29) /* Received Split Comp Error */ +#define TSI148_PCFS_PCIXSTAT_DMCRS_M (7<<26) /* max Cumulative Read Size */ +#define TSI148_PCFS_PCIXSTAT_DMOST_M (7<<23) /* max outstanding Split Trans + */ +#define TSI148_PCFS_PCIXSTAT_DMMRC_M (3<<21) /* max mem read byte count */ +#define TSI148_PCFS_PCIXSTAT_DC (1<<20) /* Device Complexity */ +#define TSI148_PCFS_PCIXSTAT_USC (1<<19) /* Unexpected Split comp */ +#define TSI148_PCFS_PCIXSTAT_SCD (1<<18) /* Split completion discard */ +#define TSI148_PCFS_PCIXSTAT_133C (1<<17) /* 133MHz capable */ +#define TSI148_PCFS_PCIXSTAT_64D (1<<16) /* 64 bit device */ +#define TSI148_PCFS_PCIXSTAT_BN_M (0xFF<<8) /* Bus number */ +#define TSI148_PCFS_PCIXSTAT_DN_M (0x1F<<3) /* Device number */ +#define TSI148_PCFS_PCIXSTAT_FN_M (7<<0) /* Function Number */ + +/* + * LCSR Registers + */ + +/* + * Outbound Translation Starting Address Lower + */ +#define TSI148_LCSR_OTSAL_M (0xFFFF<<16) /* Mask */ + +/* + * Outbound Translation Ending Address Lower + */ +#define TSI148_LCSR_OTEAL_M (0xFFFF<<16) /* Mask */ + +/* + * Outbound Translation Offset Lower + */ +#define TSI148_LCSR_OTOFFL_M (0xFFFF<<16) /* Mask */ + +/* + * Outbound Translation 2eSST Broadcast Select + */ +#define TSI148_LCSR_OTBS_M (0xFFFFF<<0) /* Mask */ + +/* + * Outbound Translation Attribute + */ +#define TSI148_LCSR_OTAT_EN (1<<31) /* Window Enable */ +#define TSI148_LCSR_OTAT_MRPFD (1<<18) /* Prefetch Disable */ + +#define TSI148_LCSR_OTAT_PFS_M (3<<16) /* Prefetch Size Mask */ +#define TSI148_LCSR_OTAT_PFS_2 (0<<16) /* 2 Cache Lines P Size */ +#define TSI148_LCSR_OTAT_PFS_4 (1<<16) /* 4 Cache Lines P Size */ +#define TSI148_LCSR_OTAT_PFS_8 (2<<16) /* 8 Cache Lines P Size */ +#define TSI148_LCSR_OTAT_PFS_16 (3<<16) /* 16 Cache Lines P Size */ + +#define TSI148_LCSR_OTAT_2eSSTM_M (7<<11) /* 2eSST Xfer Rate Mask */ +#define TSI148_LCSR_OTAT_2eSSTM_160 (0<<11) /* 160MB/s 2eSST Xfer Rate */ +#define TSI148_LCSR_OTAT_2eSSTM_267 (1<<11) /* 267MB/s 2eSST Xfer Rate */ +#define TSI148_LCSR_OTAT_2eSSTM_320 (2<<11) /* 320MB/s 2eSST Xfer Rate */ + +#define TSI148_LCSR_OTAT_TM_M (7<<8) /* Xfer Protocol Mask */ +#define TSI148_LCSR_OTAT_TM_SCT (0<<8) /* SCT Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_BLT (1<<8) /* BLT Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_MBLT (2<<8) /* MBLT Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_2eVME (3<<8) /* 2eVME Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_2eSST (4<<8) /* 2eSST Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_2eSSTB (5<<8) /* 2eSST Bcast Xfer Protocol */ + +#define TSI148_LCSR_OTAT_DBW_M (3<<6) /* Max Data Width */ +#define TSI148_LCSR_OTAT_DBW_16 (0<<6) /* 16-bit Data Width */ +#define TSI148_LCSR_OTAT_DBW_32 (1<<6) /* 32-bit Data Width */ + +#define TSI148_LCSR_OTAT_SUP (1<<5) /* Supervisory Access */ +#define TSI148_LCSR_OTAT_PGM (1<<4) /* Program Access */ + +#define TSI148_LCSR_OTAT_AMODE_M (0xf<<0) /* Address Mode Mask */ +#define TSI148_LCSR_OTAT_AMODE_A16 (0<<0) /* A16 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_A24 (1<<0) /* A24 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_A32 (2<<0) /* A32 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_A64 (4<<0) /* A32 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_CRCSR (5<<0) /* CR/CSR Address Space */ +#define TSI148_LCSR_OTAT_AMODE_USER1 (8<<0) /* User1 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_USER2 (9<<0) /* User2 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_USER3 (10<<0) /* User3 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_USER4 (11<<0) /* User4 Address Space */ + +/* + * VME Master Control Register CRG+$234 + */ +#define TSI148_LCSR_VMCTRL_VSA (1<<27) /* VMEbus Stop Ack */ +#define TSI148_LCSR_VMCTRL_VS (1<<26) /* VMEbus Stop */ +#define TSI148_LCSR_VMCTRL_DHB (1<<25) /* Device Has Bus */ +#define TSI148_LCSR_VMCTRL_DWB (1<<24) /* Device Wants Bus */ + +#define TSI148_LCSR_VMCTRL_RMWEN (1<<20) /* RMW Enable */ + +#define TSI148_LCSR_VMCTRL_ATO_M (7<<16) /* Master Access Time-out Mask + */ +#define TSI148_LCSR_VMCTRL_ATO_32 (0<<16) /* 32 us */ +#define TSI148_LCSR_VMCTRL_ATO_128 (1<<16) /* 128 us */ +#define TSI148_LCSR_VMCTRL_ATO_512 (2<<16) /* 512 us */ +#define TSI148_LCSR_VMCTRL_ATO_2M (3<<16) /* 2 ms */ +#define TSI148_LCSR_VMCTRL_ATO_8M (4<<16) /* 8 ms */ +#define TSI148_LCSR_VMCTRL_ATO_32M (5<<16) /* 32 ms */ +#define TSI148_LCSR_VMCTRL_ATO_128M (6<<16) /* 128 ms */ +#define TSI148_LCSR_VMCTRL_ATO_DIS (7<<16) /* Disabled */ + +#define TSI148_LCSR_VMCTRL_VTOFF_M (7<<12) /* VMEbus Master Time off */ +#define TSI148_LCSR_VMCTRL_VTOFF_0 (0<<12) /* 0us */ +#define TSI148_LCSR_VMCTRL_VTOFF_1 (1<<12) /* 1us */ +#define TSI148_LCSR_VMCTRL_VTOFF_2 (2<<12) /* 2us */ +#define TSI148_LCSR_VMCTRL_VTOFF_4 (3<<12) /* 4us */ +#define TSI148_LCSR_VMCTRL_VTOFF_8 (4<<12) /* 8us */ +#define TSI148_LCSR_VMCTRL_VTOFF_16 (5<<12) /* 16us */ +#define TSI148_LCSR_VMCTRL_VTOFF_32 (6<<12) /* 32us */ +#define TSI148_LCSR_VMCTRL_VTOFF_64 (7<<12) /* 64us */ + +#define TSI148_LCSR_VMCTRL_VTON_M (7<<8) /* VMEbus Master Time On */ +#define TSI148_LCSR_VMCTRL_VTON_4 (0<<8) /* 8us */ +#define TSI148_LCSR_VMCTRL_VTON_8 (1<<8) /* 8us */ +#define TSI148_LCSR_VMCTRL_VTON_16 (2<<8) /* 16us */ +#define TSI148_LCSR_VMCTRL_VTON_32 (3<<8) /* 32us */ +#define TSI148_LCSR_VMCTRL_VTON_64 (4<<8) /* 64us */ +#define TSI148_LCSR_VMCTRL_VTON_128 (5<<8) /* 128us */ +#define TSI148_LCSR_VMCTRL_VTON_256 (6<<8) /* 256us */ +#define TSI148_LCSR_VMCTRL_VTON_512 (7<<8) /* 512us */ + +#define TSI148_LCSR_VMCTRL_VREL_M (3<<3) /* VMEbus Master Rel Mode Mask + */ +#define TSI148_LCSR_VMCTRL_VREL_T_D (0<<3) /* Time on or Done */ +#define TSI148_LCSR_VMCTRL_VREL_T_R_D (1<<3) /* Time on and REQ or Done */ +#define TSI148_LCSR_VMCTRL_VREL_T_B_D (2<<3) /* Time on and BCLR or Done */ +#define TSI148_LCSR_VMCTRL_VREL_T_D_R (3<<3) /* Time on or Done and REQ */ + +#define TSI148_LCSR_VMCTRL_VFAIR (1<<2) /* VMEbus Master Fair Mode */ +#define TSI148_LCSR_VMCTRL_VREQL_M (3<<0) /* VMEbus Master Req Level Mask + */ + +/* + * VMEbus Control Register CRG+$238 + */ +#define TSI148_LCSR_VCTRL_LRE (1<<31) /* Late Retry Enable */ + +#define TSI148_LCSR_VCTRL_DLT_M (0xF<<24) /* Deadlock Timer */ +#define TSI148_LCSR_VCTRL_DLT_OFF (0<<24) /* Deadlock Timer Off */ +#define TSI148_LCSR_VCTRL_DLT_16 (1<<24) /* 16 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_32 (2<<24) /* 32 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_64 (3<<24) /* 64 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_128 (4<<24) /* 128 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_256 (5<<24) /* 256 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_512 (6<<24) /* 512 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_1024 (7<<24) /* 1024 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_2048 (8<<24) /* 2048 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_4096 (9<<24) /* 4096 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_8192 (0xA<<24) /* 8192 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_16384 (0xB<<24) /* 16384 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_32768 (0xC<<24) /* 32768 VCLKS */ + +#define TSI148_LCSR_VCTRL_NERBB (1<<20) /* No Early Release of Bus Busy + */ + +#define TSI148_LCSR_VCTRL_SRESET (1<<17) /* System Reset */ +#define TSI148_LCSR_VCTRL_LRESET (1<<16) /* Local Reset */ + +#define TSI148_LCSR_VCTRL_SFAILAI (1<<15) /* SYSFAIL Auto Slot ID */ +#define TSI148_LCSR_VCTRL_BID_M (0x1F<<8) /* Broadcast ID Mask */ + +#define TSI148_LCSR_VCTRL_ATOEN (1<<7) /* Arbiter Time-out Enable */ +#define TSI148_LCSR_VCTRL_ROBIN (1<<6) /* VMEbus Round Robin */ + +#define TSI148_LCSR_VCTRL_GTO_M (7<<0) /* VMEbus Global Time-out Mask + */ +#define TSI148_LCSR_VCTRL_GTO_8 (0<<0) /* 8 us */ +#define TSI148_LCSR_VCTRL_GTO_16 (1<<0) /* 16 us */ +#define TSI148_LCSR_VCTRL_GTO_32 (2<<0) /* 32 us */ +#define TSI148_LCSR_VCTRL_GTO_64 (3<<0) /* 64 us */ +#define TSI148_LCSR_VCTRL_GTO_128 (4<<0) /* 128 us */ +#define TSI148_LCSR_VCTRL_GTO_256 (5<<0) /* 256 us */ +#define TSI148_LCSR_VCTRL_GTO_512 (6<<0) /* 512 us */ +#define TSI148_LCSR_VCTRL_GTO_DIS (7<<0) /* Disabled */ + +/* + * VMEbus Status Register CRG + $23C + */ +#define TSI148_LCSR_VSTAT_CPURST (1<<15) /* Clear power up reset */ +#define TSI148_LCSR_VSTAT_BRDFL (1<<14) /* Board fail */ +#define TSI148_LCSR_VSTAT_PURSTS (1<<12) /* Power up reset status */ +#define TSI148_LCSR_VSTAT_BDFAILS (1<<11) /* Board Fail Status */ +#define TSI148_LCSR_VSTAT_SYSFAILS (1<<10) /* System Fail Status */ +#define TSI148_LCSR_VSTAT_ACFAILS (1<<9) /* AC fail status */ +#define TSI148_LCSR_VSTAT_SCONS (1<<8) /* System Cont Status */ +#define TSI148_LCSR_VSTAT_GAP (1<<5) /* Geographic Addr Parity */ +#define TSI148_LCSR_VSTAT_GA_M (0x1F<<0) /* Geographic Addr Mask */ + +/* + * PCI Configuration Status Register CRG+$240 + */ +#define TSI148_LCSR_PSTAT_REQ64S (1<<6) /* Request 64 status set */ +#define TSI148_LCSR_PSTAT_M66ENS (1<<5) /* M66ENS 66Mhz enable */ +#define TSI148_LCSR_PSTAT_FRAMES (1<<4) /* Frame Status */ +#define TSI148_LCSR_PSTAT_IRDYS (1<<3) /* IRDY status */ +#define TSI148_LCSR_PSTAT_DEVSELS (1<<2) /* DEVL status */ +#define TSI148_LCSR_PSTAT_STOPS (1<<1) /* STOP status */ +#define TSI148_LCSR_PSTAT_TRDYS (1<<0) /* TRDY status */ + +/* + * VMEbus Exception Attributes Register CRG + $268 + */ +#define TSI148_LCSR_VEAT_VES (1<<31) /* Status */ +#define TSI148_LCSR_VEAT_VEOF (1<<30) /* Overflow */ +#define TSI148_LCSR_VEAT_VESCL (1<<29) /* Status Clear */ +#define TSI148_LCSR_VEAT_2EOT (1<<21) /* 2e Odd Termination */ +#define TSI148_LCSR_VEAT_2EST (1<<20) /* 2e Slave terminated */ +#define TSI148_LCSR_VEAT_BERR (1<<19) /* Bus Error */ +#define TSI148_LCSR_VEAT_LWORD (1<<18) /* LWORD_ signal state */ +#define TSI148_LCSR_VEAT_WRITE (1<<17) /* WRITE_ signal state */ +#define TSI148_LCSR_VEAT_IACK (1<<16) /* IACK_ signal state */ +#define TSI148_LCSR_VEAT_DS1 (1<<15) /* DS1_ signal state */ +#define TSI148_LCSR_VEAT_DS0 (1<<14) /* DS0_ signal state */ +#define TSI148_LCSR_VEAT_AM_M (0x3F<<8) /* Address Mode Mask */ +#define TSI148_LCSR_VEAT_XAM_M (0xFF<<0) /* Master AMode Mask */ + + +/* + * VMEbus PCI Error Diagnostics PCI/X Attributes Register CRG + $280 + */ +#define TSI148_LCSR_EDPAT_EDPCL (1<<29) + +/* + * Inbound Translation Starting Address Lower + */ +#define TSI148_LCSR_ITSAL6432_M (0xFFFF<<16) /* Mask */ +#define TSI148_LCSR_ITSAL24_M (0x00FFF<<12) /* Mask */ +#define TSI148_LCSR_ITSAL16_M (0x0000FFF<<4) /* Mask */ + +/* + * Inbound Translation Ending Address Lower + */ +#define TSI148_LCSR_ITEAL6432_M (0xFFFF<<16) /* Mask */ +#define TSI148_LCSR_ITEAL24_M (0x00FFF<<12) /* Mask */ +#define TSI148_LCSR_ITEAL16_M (0x0000FFF<<4) /* Mask */ + +/* + * Inbound Translation Offset Lower + */ +#define TSI148_LCSR_ITOFFL6432_M (0xFFFF<<16) /* Mask */ +#define TSI148_LCSR_ITOFFL24_M (0xFFFFF<<12) /* Mask */ +#define TSI148_LCSR_ITOFFL16_M (0xFFFFFFF<<4) /* Mask */ + +/* + * Inbound Translation Attribute + */ +#define TSI148_LCSR_ITAT_EN (1<<31) /* Window Enable */ +#define TSI148_LCSR_ITAT_TH (1<<18) /* Prefetch Threshold */ + +#define TSI148_LCSR_ITAT_VFS_M (3<<16) /* Virtual FIFO Size Mask */ +#define TSI148_LCSR_ITAT_VFS_64 (0<<16) /* 64 bytes Virtual FIFO Size */ +#define TSI148_LCSR_ITAT_VFS_128 (1<<16) /* 128 bytes Virtual FIFO Sz */ +#define TSI148_LCSR_ITAT_VFS_256 (2<<16) /* 256 bytes Virtual FIFO Sz */ +#define TSI148_LCSR_ITAT_VFS_512 (3<<16) /* 512 bytes Virtual FIFO Sz */ + +#define TSI148_LCSR_ITAT_2eSSTM_M (7<<12) /* 2eSST Xfer Rate Mask */ +#define TSI148_LCSR_ITAT_2eSSTM_160 (0<<12) /* 160MB/s 2eSST Xfer Rate */ +#define TSI148_LCSR_ITAT_2eSSTM_267 (1<<12) /* 267MB/s 2eSST Xfer Rate */ +#define TSI148_LCSR_ITAT_2eSSTM_320 (2<<12) /* 320MB/s 2eSST Xfer Rate */ + +#define TSI148_LCSR_ITAT_2eSSTB (1<<11) /* 2eSST Bcast Xfer Protocol */ +#define TSI148_LCSR_ITAT_2eSST (1<<10) /* 2eSST Xfer Protocol */ +#define TSI148_LCSR_ITAT_2eVME (1<<9) /* 2eVME Xfer Protocol */ +#define TSI148_LCSR_ITAT_MBLT (1<<8) /* MBLT Xfer Protocol */ +#define TSI148_LCSR_ITAT_BLT (1<<7) /* BLT Xfer Protocol */ + +#define TSI148_LCSR_ITAT_AS_M (7<<4) /* Address Space Mask */ +#define TSI148_LCSR_ITAT_AS_A16 (0<<4) /* A16 Address Space */ +#define TSI148_LCSR_ITAT_AS_A24 (1<<4) /* A24 Address Space */ +#define TSI148_LCSR_ITAT_AS_A32 (2<<4) /* A32 Address Space */ +#define TSI148_LCSR_ITAT_AS_A64 (4<<4) /* A64 Address Space */ + +#define TSI148_LCSR_ITAT_SUPR (1<<3) /* Supervisor Access */ +#define TSI148_LCSR_ITAT_NPRIV (1<<2) /* Non-Priv (User) Access */ +#define TSI148_LCSR_ITAT_PGM (1<<1) /* Program Access */ +#define TSI148_LCSR_ITAT_DATA (1<<0) /* Data Access */ + +/* + * GCSR Base Address Lower Address CRG +$404 + */ +#define TSI148_LCSR_GBAL_M (0x7FFFFFF<<5) /* Mask */ + +/* + * GCSR Attribute Register CRG + $408 + */ +#define TSI148_LCSR_GCSRAT_EN (1<<7) /* Enable access to GCSR */ + +#define TSI148_LCSR_GCSRAT_AS_M (7<<4) /* Address Space Mask */ +#define TSI148_LCSR_GCSRAT_AS_A16 (0<<4) /* Address Space 16 */ +#define TSI148_LCSR_GCSRAT_AS_A24 (1<<4) /* Address Space 24 */ +#define TSI148_LCSR_GCSRAT_AS_A32 (2<<4) /* Address Space 32 */ +#define TSI148_LCSR_GCSRAT_AS_A64 (4<<4) /* Address Space 64 */ + +#define TSI148_LCSR_GCSRAT_SUPR (1<<3) /* Sup set -GCSR decoder */ +#define TSI148_LCSR_GCSRAT_NPRIV (1<<2) /* Non-Privliged set - CGSR */ +#define TSI148_LCSR_GCSRAT_PGM (1<<1) /* Program set - GCSR decoder */ +#define TSI148_LCSR_GCSRAT_DATA (1<<0) /* DATA set GCSR decoder */ + +/* + * CRG Base Address Lower Address CRG + $410 + */ +#define TSI148_LCSR_CBAL_M (0xFFFFF<<12) + +/* + * CRG Attribute Register CRG + $414 + */ +#define TSI148_LCSR_CRGAT_EN (1<<7) /* Enable PRG Access */ + +#define TSI148_LCSR_CRGAT_AS_M (7<<4) /* Address Space */ +#define TSI148_LCSR_CRGAT_AS_A16 (0<<4) /* Address Space 16 */ +#define TSI148_LCSR_CRGAT_AS_A24 (1<<4) /* Address Space 24 */ +#define TSI148_LCSR_CRGAT_AS_A32 (2<<4) /* Address Space 32 */ +#define TSI148_LCSR_CRGAT_AS_A64 (4<<4) /* Address Space 64 */ + +#define TSI148_LCSR_CRGAT_SUPR (1<<3) /* Supervisor Access */ +#define TSI148_LCSR_CRGAT_NPRIV (1<<2) /* Non-Privliged(User) Access */ +#define TSI148_LCSR_CRGAT_PGM (1<<1) /* Program Access */ +#define TSI148_LCSR_CRGAT_DATA (1<<0) /* Data Access */ + +/* + * CR/CSR Offset Lower Register CRG + $41C + */ +#define TSI148_LCSR_CROL_M (0x1FFF<<19) /* Mask */ + +/* + * CR/CSR Attribute register CRG + $420 + */ +#define TSI148_LCSR_CRAT_EN (1<<7) /* Enable access to CR/CSR */ + +/* + * Location Monitor base address lower register CRG + $428 + */ +#define TSI148_LCSR_LMBAL_M (0x7FFFFFF<<5) /* Mask */ + +/* + * Location Monitor Attribute Register CRG + $42C + */ +#define TSI148_LCSR_LMAT_EN (1<<7) /* Enable Location Monitor */ + +#define TSI148_LCSR_LMAT_AS_M (7<<4) /* Address Space MASK */ +#define TSI148_LCSR_LMAT_AS_A16 (0<<4) /* A16 */ +#define TSI148_LCSR_LMAT_AS_A24 (1<<4) /* A24 */ +#define TSI148_LCSR_LMAT_AS_A32 (2<<4) /* A32 */ +#define TSI148_LCSR_LMAT_AS_A64 (4<<4) /* A64 */ + +#define TSI148_LCSR_LMAT_SUPR (1<<3) /* Supervisor Access */ +#define TSI148_LCSR_LMAT_NPRIV (1<<2) /* Non-Priv (User) Access */ +#define TSI148_LCSR_LMAT_PGM (1<<1) /* Program Access */ +#define TSI148_LCSR_LMAT_DATA (1<<0) /* Data Access */ + +/* + * Broadcast Pulse Generator Timer Register CRG + $438 + */ +#define TSI148_LCSR_BPGTR_BPGT_M (0xFFFF<<0) /* Mask */ + +/* + * Broadcast Programmable Clock Timer Register CRG + $43C + */ +#define TSI148_LCSR_BPCTR_BPCT_M (0xFFFFFF<<0) /* Mask */ + +/* + * VMEbus Interrupt Control Register CRG + $43C + */ +#define TSI148_LCSR_VICR_CNTS_M (3<<22) /* Cntr Source MASK */ +#define TSI148_LCSR_VICR_CNTS_DIS (1<<22) /* Cntr Disable */ +#define TSI148_LCSR_VICR_CNTS_IRQ1 (2<<22) /* IRQ1 to Cntr */ +#define TSI148_LCSR_VICR_CNTS_IRQ2 (3<<22) /* IRQ2 to Cntr */ + +#define TSI148_LCSR_VICR_EDGIS_M (3<<20) /* Edge interrupt MASK */ +#define TSI148_LCSR_VICR_EDGIS_DIS (1<<20) /* Edge interrupt Disable */ +#define TSI148_LCSR_VICR_EDGIS_IRQ1 (2<<20) /* IRQ1 to Edge */ +#define TSI148_LCSR_VICR_EDGIS_IRQ2 (3<<20) /* IRQ2 to Edge */ + +#define TSI148_LCSR_VICR_IRQIF_M (3<<18) /* IRQ1* Function MASK */ +#define TSI148_LCSR_VICR_IRQIF_NORM (1<<18) /* Normal */ +#define TSI148_LCSR_VICR_IRQIF_PULSE (2<<18) /* Pulse Generator */ +#define TSI148_LCSR_VICR_IRQIF_PROG (3<<18) /* Programmable Clock */ +#define TSI148_LCSR_VICR_IRQIF_1U (4<<18) /* 1us Clock */ + +#define TSI148_LCSR_VICR_IRQ2F_M (3<<16) /* IRQ2* Function MASK */ +#define TSI148_LCSR_VICR_IRQ2F_NORM (1<<16) /* Normal */ +#define TSI148_LCSR_VICR_IRQ2F_PULSE (2<<16) /* Pulse Generator */ +#define TSI148_LCSR_VICR_IRQ2F_PROG (3<<16) /* Programmable Clock */ +#define TSI148_LCSR_VICR_IRQ2F_1U (4<<16) /* 1us Clock */ + +#define TSI148_LCSR_VICR_BIP (1<<15) /* Broadcast Interrupt Pulse */ + +#define TSI148_LCSR_VICR_IRQC (1<<12) /* VMEbus IRQ Clear */ +#define TSI148_LCSR_VICR_IRQS (1<<11) /* VMEbus IRQ Status */ + +#define TSI148_LCSR_VICR_IRQL_M (7<<8) /* VMEbus SW IRQ Level Mask */ +#define TSI148_LCSR_VICR_IRQL_1 (1<<8) /* VMEbus SW IRQ Level 1 */ +#define TSI148_LCSR_VICR_IRQL_2 (2<<8) /* VMEbus SW IRQ Level 2 */ +#define TSI148_LCSR_VICR_IRQL_3 (3<<8) /* VMEbus SW IRQ Level 3 */ +#define TSI148_LCSR_VICR_IRQL_4 (4<<8) /* VMEbus SW IRQ Level 4 */ +#define TSI148_LCSR_VICR_IRQL_5 (5<<8) /* VMEbus SW IRQ Level 5 */ +#define TSI148_LCSR_VICR_IRQL_6 (6<<8) /* VMEbus SW IRQ Level 6 */ +#define TSI148_LCSR_VICR_IRQL_7 (7<<8) /* VMEbus SW IRQ Level 7 */ + +static const int TSI148_LCSR_VICR_IRQL[8] = { 0, TSI148_LCSR_VICR_IRQL_1, + TSI148_LCSR_VICR_IRQL_2, TSI148_LCSR_VICR_IRQL_3, + TSI148_LCSR_VICR_IRQL_4, TSI148_LCSR_VICR_IRQL_5, + TSI148_LCSR_VICR_IRQL_6, TSI148_LCSR_VICR_IRQL_7 }; + +#define TSI148_LCSR_VICR_STID_M (0xFF<<0) /* Status/ID Mask */ + +/* + * Interrupt Enable Register CRG + $440 + */ +#define TSI148_LCSR_INTEN_DMA1EN (1<<25) /* DMAC 1 */ +#define TSI148_LCSR_INTEN_DMA0EN (1<<24) /* DMAC 0 */ +#define TSI148_LCSR_INTEN_LM3EN (1<<23) /* Location Monitor 3 */ +#define TSI148_LCSR_INTEN_LM2EN (1<<22) /* Location Monitor 2 */ +#define TSI148_LCSR_INTEN_LM1EN (1<<21) /* Location Monitor 1 */ +#define TSI148_LCSR_INTEN_LM0EN (1<<20) /* Location Monitor 0 */ +#define TSI148_LCSR_INTEN_MB3EN (1<<19) /* Mail Box 3 */ +#define TSI148_LCSR_INTEN_MB2EN (1<<18) /* Mail Box 2 */ +#define TSI148_LCSR_INTEN_MB1EN (1<<17) /* Mail Box 1 */ +#define TSI148_LCSR_INTEN_MB0EN (1<<16) /* Mail Box 0 */ +#define TSI148_LCSR_INTEN_PERREN (1<<13) /* PCI/X Error */ +#define TSI148_LCSR_INTEN_VERREN (1<<12) /* VMEbus Error */ +#define TSI148_LCSR_INTEN_VIEEN (1<<11) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTEN_IACKEN (1<<10) /* IACK */ +#define TSI148_LCSR_INTEN_SYSFLEN (1<<9) /* System Fail */ +#define TSI148_LCSR_INTEN_ACFLEN (1<<8) /* AC Fail */ +#define TSI148_LCSR_INTEN_IRQ7EN (1<<7) /* IRQ7 */ +#define TSI148_LCSR_INTEN_IRQ6EN (1<<6) /* IRQ6 */ +#define TSI148_LCSR_INTEN_IRQ5EN (1<<5) /* IRQ5 */ +#define TSI148_LCSR_INTEN_IRQ4EN (1<<4) /* IRQ4 */ +#define TSI148_LCSR_INTEN_IRQ3EN (1<<3) /* IRQ3 */ +#define TSI148_LCSR_INTEN_IRQ2EN (1<<2) /* IRQ2 */ +#define TSI148_LCSR_INTEN_IRQ1EN (1<<1) /* IRQ1 */ + +static const int TSI148_LCSR_INTEN_LMEN[4] = { TSI148_LCSR_INTEN_LM0EN, + TSI148_LCSR_INTEN_LM1EN, + TSI148_LCSR_INTEN_LM2EN, + TSI148_LCSR_INTEN_LM3EN }; + +static const int TSI148_LCSR_INTEN_IRQEN[7] = { TSI148_LCSR_INTEN_IRQ1EN, + TSI148_LCSR_INTEN_IRQ2EN, + TSI148_LCSR_INTEN_IRQ3EN, + TSI148_LCSR_INTEN_IRQ4EN, + TSI148_LCSR_INTEN_IRQ5EN, + TSI148_LCSR_INTEN_IRQ6EN, + TSI148_LCSR_INTEN_IRQ7EN }; + +/* + * Interrupt Enable Out Register CRG + $444 + */ +#define TSI148_LCSR_INTEO_DMA1EO (1<<25) /* DMAC 1 */ +#define TSI148_LCSR_INTEO_DMA0EO (1<<24) /* DMAC 0 */ +#define TSI148_LCSR_INTEO_LM3EO (1<<23) /* Loc Monitor 3 */ +#define TSI148_LCSR_INTEO_LM2EO (1<<22) /* Loc Monitor 2 */ +#define TSI148_LCSR_INTEO_LM1EO (1<<21) /* Loc Monitor 1 */ +#define TSI148_LCSR_INTEO_LM0EO (1<<20) /* Location Monitor 0 */ +#define TSI148_LCSR_INTEO_MB3EO (1<<19) /* Mail Box 3 */ +#define TSI148_LCSR_INTEO_MB2EO (1<<18) /* Mail Box 2 */ +#define TSI148_LCSR_INTEO_MB1EO (1<<17) /* Mail Box 1 */ +#define TSI148_LCSR_INTEO_MB0EO (1<<16) /* Mail Box 0 */ +#define TSI148_LCSR_INTEO_PERREO (1<<13) /* PCI/X Error */ +#define TSI148_LCSR_INTEO_VERREO (1<<12) /* VMEbus Error */ +#define TSI148_LCSR_INTEO_VIEEO (1<<11) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTEO_IACKEO (1<<10) /* IACK */ +#define TSI148_LCSR_INTEO_SYSFLEO (1<<9) /* System Fail */ +#define TSI148_LCSR_INTEO_ACFLEO (1<<8) /* AC Fail */ +#define TSI148_LCSR_INTEO_IRQ7EO (1<<7) /* IRQ7 */ +#define TSI148_LCSR_INTEO_IRQ6EO (1<<6) /* IRQ6 */ +#define TSI148_LCSR_INTEO_IRQ5EO (1<<5) /* IRQ5 */ +#define TSI148_LCSR_INTEO_IRQ4EO (1<<4) /* IRQ4 */ +#define TSI148_LCSR_INTEO_IRQ3EO (1<<3) /* IRQ3 */ +#define TSI148_LCSR_INTEO_IRQ2EO (1<<2) /* IRQ2 */ +#define TSI148_LCSR_INTEO_IRQ1EO (1<<1) /* IRQ1 */ + +static const int TSI148_LCSR_INTEO_LMEO[4] = { TSI148_LCSR_INTEO_LM0EO, + TSI148_LCSR_INTEO_LM1EO, + TSI148_LCSR_INTEO_LM2EO, + TSI148_LCSR_INTEO_LM3EO }; + +static const int TSI148_LCSR_INTEO_IRQEO[7] = { TSI148_LCSR_INTEO_IRQ1EO, + TSI148_LCSR_INTEO_IRQ2EO, + TSI148_LCSR_INTEO_IRQ3EO, + TSI148_LCSR_INTEO_IRQ4EO, + TSI148_LCSR_INTEO_IRQ5EO, + TSI148_LCSR_INTEO_IRQ6EO, + TSI148_LCSR_INTEO_IRQ7EO }; + +/* + * Interrupt Status Register CRG + $448 + */ +#define TSI148_LCSR_INTS_DMA1S (1<<25) /* DMA 1 */ +#define TSI148_LCSR_INTS_DMA0S (1<<24) /* DMA 0 */ +#define TSI148_LCSR_INTS_LM3S (1<<23) /* Location Monitor 3 */ +#define TSI148_LCSR_INTS_LM2S (1<<22) /* Location Monitor 2 */ +#define TSI148_LCSR_INTS_LM1S (1<<21) /* Location Monitor 1 */ +#define TSI148_LCSR_INTS_LM0S (1<<20) /* Location Monitor 0 */ +#define TSI148_LCSR_INTS_MB3S (1<<19) /* Mail Box 3 */ +#define TSI148_LCSR_INTS_MB2S (1<<18) /* Mail Box 2 */ +#define TSI148_LCSR_INTS_MB1S (1<<17) /* Mail Box 1 */ +#define TSI148_LCSR_INTS_MB0S (1<<16) /* Mail Box 0 */ +#define TSI148_LCSR_INTS_PERRS (1<<13) /* PCI/X Error */ +#define TSI148_LCSR_INTS_VERRS (1<<12) /* VMEbus Error */ +#define TSI148_LCSR_INTS_VIES (1<<11) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTS_IACKS (1<<10) /* IACK */ +#define TSI148_LCSR_INTS_SYSFLS (1<<9) /* System Fail */ +#define TSI148_LCSR_INTS_ACFLS (1<<8) /* AC Fail */ +#define TSI148_LCSR_INTS_IRQ7S (1<<7) /* IRQ7 */ +#define TSI148_LCSR_INTS_IRQ6S (1<<6) /* IRQ6 */ +#define TSI148_LCSR_INTS_IRQ5S (1<<5) /* IRQ5 */ +#define TSI148_LCSR_INTS_IRQ4S (1<<4) /* IRQ4 */ +#define TSI148_LCSR_INTS_IRQ3S (1<<3) /* IRQ3 */ +#define TSI148_LCSR_INTS_IRQ2S (1<<2) /* IRQ2 */ +#define TSI148_LCSR_INTS_IRQ1S (1<<1) /* IRQ1 */ + +static const int TSI148_LCSR_INTS_LMS[4] = { TSI148_LCSR_INTS_LM0S, + TSI148_LCSR_INTS_LM1S, + TSI148_LCSR_INTS_LM2S, + TSI148_LCSR_INTS_LM3S }; + +static const int TSI148_LCSR_INTS_MBS[4] = { TSI148_LCSR_INTS_MB0S, + TSI148_LCSR_INTS_MB1S, + TSI148_LCSR_INTS_MB2S, + TSI148_LCSR_INTS_MB3S }; + +/* + * Interrupt Clear Register CRG + $44C + */ +#define TSI148_LCSR_INTC_DMA1C (1<<25) /* DMA 1 */ +#define TSI148_LCSR_INTC_DMA0C (1<<24) /* DMA 0 */ +#define TSI148_LCSR_INTC_LM3C (1<<23) /* Location Monitor 3 */ +#define TSI148_LCSR_INTC_LM2C (1<<22) /* Location Monitor 2 */ +#define TSI148_LCSR_INTC_LM1C (1<<21) /* Location Monitor 1 */ +#define TSI148_LCSR_INTC_LM0C (1<<20) /* Location Monitor 0 */ +#define TSI148_LCSR_INTC_MB3C (1<<19) /* Mail Box 3 */ +#define TSI148_LCSR_INTC_MB2C (1<<18) /* Mail Box 2 */ +#define TSI148_LCSR_INTC_MB1C (1<<17) /* Mail Box 1 */ +#define TSI148_LCSR_INTC_MB0C (1<<16) /* Mail Box 0 */ +#define TSI148_LCSR_INTC_PERRC (1<<13) /* VMEbus Error */ +#define TSI148_LCSR_INTC_VERRC (1<<12) /* VMEbus Access Time-out */ +#define TSI148_LCSR_INTC_VIEC (1<<11) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTC_IACKC (1<<10) /* IACK */ +#define TSI148_LCSR_INTC_SYSFLC (1<<9) /* System Fail */ +#define TSI148_LCSR_INTC_ACFLC (1<<8) /* AC Fail */ + +static const int TSI148_LCSR_INTC_LMC[4] = { TSI148_LCSR_INTC_LM0C, + TSI148_LCSR_INTC_LM1C, + TSI148_LCSR_INTC_LM2C, + TSI148_LCSR_INTC_LM3C }; + +static const int TSI148_LCSR_INTC_MBC[4] = { TSI148_LCSR_INTC_MB0C, + TSI148_LCSR_INTC_MB1C, + TSI148_LCSR_INTC_MB2C, + TSI148_LCSR_INTC_MB3C }; + +/* + * Interrupt Map Register 1 CRG + $458 + */ +#define TSI148_LCSR_INTM1_DMA1M_M (3<<18) /* DMA 1 */ +#define TSI148_LCSR_INTM1_DMA0M_M (3<<16) /* DMA 0 */ +#define TSI148_LCSR_INTM1_LM3M_M (3<<14) /* Location Monitor 3 */ +#define TSI148_LCSR_INTM1_LM2M_M (3<<12) /* Location Monitor 2 */ +#define TSI148_LCSR_INTM1_LM1M_M (3<<10) /* Location Monitor 1 */ +#define TSI148_LCSR_INTM1_LM0M_M (3<<8) /* Location Monitor 0 */ +#define TSI148_LCSR_INTM1_MB3M_M (3<<6) /* Mail Box 3 */ +#define TSI148_LCSR_INTM1_MB2M_M (3<<4) /* Mail Box 2 */ +#define TSI148_LCSR_INTM1_MB1M_M (3<<2) /* Mail Box 1 */ +#define TSI148_LCSR_INTM1_MB0M_M (3<<0) /* Mail Box 0 */ + +/* + * Interrupt Map Register 2 CRG + $45C + */ +#define TSI148_LCSR_INTM2_PERRM_M (3<<26) /* PCI Bus Error */ +#define TSI148_LCSR_INTM2_VERRM_M (3<<24) /* VMEbus Error */ +#define TSI148_LCSR_INTM2_VIEM_M (3<<22) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTM2_IACKM_M (3<<20) /* IACK */ +#define TSI148_LCSR_INTM2_SYSFLM_M (3<<18) /* System Fail */ +#define TSI148_LCSR_INTM2_ACFLM_M (3<<16) /* AC Fail */ +#define TSI148_LCSR_INTM2_IRQ7M_M (3<<14) /* IRQ7 */ +#define TSI148_LCSR_INTM2_IRQ6M_M (3<<12) /* IRQ6 */ +#define TSI148_LCSR_INTM2_IRQ5M_M (3<<10) /* IRQ5 */ +#define TSI148_LCSR_INTM2_IRQ4M_M (3<<8) /* IRQ4 */ +#define TSI148_LCSR_INTM2_IRQ3M_M (3<<6) /* IRQ3 */ +#define TSI148_LCSR_INTM2_IRQ2M_M (3<<4) /* IRQ2 */ +#define TSI148_LCSR_INTM2_IRQ1M_M (3<<2) /* IRQ1 */ + +/* + * DMA Control (0-1) Registers CRG + $500 + */ +#define TSI148_LCSR_DCTL_ABT (1<<27) /* Abort */ +#define TSI148_LCSR_DCTL_PAU (1<<26) /* Pause */ +#define TSI148_LCSR_DCTL_DGO (1<<25) /* DMA Go */ + +#define TSI148_LCSR_DCTL_MOD (1<<23) /* Mode */ + +#define TSI148_LCSR_DCTL_VBKS_M (7<<12) /* VMEbus block Size MASK */ +#define TSI148_LCSR_DCTL_VBKS_32 (0<<12) /* VMEbus block Size 32 */ +#define TSI148_LCSR_DCTL_VBKS_64 (1<<12) /* VMEbus block Size 64 */ +#define TSI148_LCSR_DCTL_VBKS_128 (2<<12) /* VMEbus block Size 128 */ +#define TSI148_LCSR_DCTL_VBKS_256 (3<<12) /* VMEbus block Size 256 */ +#define TSI148_LCSR_DCTL_VBKS_512 (4<<12) /* VMEbus block Size 512 */ +#define TSI148_LCSR_DCTL_VBKS_1024 (5<<12) /* VMEbus block Size 1024 */ +#define TSI148_LCSR_DCTL_VBKS_2048 (6<<12) /* VMEbus block Size 2048 */ +#define TSI148_LCSR_DCTL_VBKS_4096 (7<<12) /* VMEbus block Size 4096 */ + +#define TSI148_LCSR_DCTL_VBOT_M (7<<8) /* VMEbus back-off MASK */ +#define TSI148_LCSR_DCTL_VBOT_0 (0<<8) /* VMEbus back-off 0us */ +#define TSI148_LCSR_DCTL_VBOT_1 (1<<8) /* VMEbus back-off 1us */ +#define TSI148_LCSR_DCTL_VBOT_2 (2<<8) /* VMEbus back-off 2us */ +#define TSI148_LCSR_DCTL_VBOT_4 (3<<8) /* VMEbus back-off 4us */ +#define TSI148_LCSR_DCTL_VBOT_8 (4<<8) /* VMEbus back-off 8us */ +#define TSI148_LCSR_DCTL_VBOT_16 (5<<8) /* VMEbus back-off 16us */ +#define TSI148_LCSR_DCTL_VBOT_32 (6<<8) /* VMEbus back-off 32us */ +#define TSI148_LCSR_DCTL_VBOT_64 (7<<8) /* VMEbus back-off 64us */ + +#define TSI148_LCSR_DCTL_PBKS_M (7<<4) /* PCI block size MASK */ +#define TSI148_LCSR_DCTL_PBKS_32 (0<<4) /* PCI block size 32 bytes */ +#define TSI148_LCSR_DCTL_PBKS_64 (1<<4) /* PCI block size 64 bytes */ +#define TSI148_LCSR_DCTL_PBKS_128 (2<<4) /* PCI block size 128 bytes */ +#define TSI148_LCSR_DCTL_PBKS_256 (3<<4) /* PCI block size 256 bytes */ +#define TSI148_LCSR_DCTL_PBKS_512 (4<<4) /* PCI block size 512 bytes */ +#define TSI148_LCSR_DCTL_PBKS_1024 (5<<4) /* PCI block size 1024 bytes */ +#define TSI148_LCSR_DCTL_PBKS_2048 (6<<4) /* PCI block size 2048 bytes */ +#define TSI148_LCSR_DCTL_PBKS_4096 (7<<4) /* PCI block size 4096 bytes */ + +#define TSI148_LCSR_DCTL_PBOT_M (7<<0) /* PCI back off MASK */ +#define TSI148_LCSR_DCTL_PBOT_0 (0<<0) /* PCI back off 0us */ +#define TSI148_LCSR_DCTL_PBOT_1 (1<<0) /* PCI back off 1us */ +#define TSI148_LCSR_DCTL_PBOT_2 (2<<0) /* PCI back off 2us */ +#define TSI148_LCSR_DCTL_PBOT_4 (3<<0) /* PCI back off 3us */ +#define TSI148_LCSR_DCTL_PBOT_8 (4<<0) /* PCI back off 4us */ +#define TSI148_LCSR_DCTL_PBOT_16 (5<<0) /* PCI back off 8us */ +#define TSI148_LCSR_DCTL_PBOT_32 (6<<0) /* PCI back off 16us */ +#define TSI148_LCSR_DCTL_PBOT_64 (7<<0) /* PCI back off 32us */ + +/* + * DMA Status Registers (0-1) CRG + $504 + */ +#define TSI148_LCSR_DSTA_SMA (1<<31) /* PCI Signalled Master Abt */ +#define TSI148_LCSR_DSTA_RTA (1<<30) /* PCI Received Target Abt */ +#define TSI148_LCSR_DSTA_MRC (1<<29) /* PCI Max Retry Count */ +#define TSI148_LCSR_DSTA_VBE (1<<28) /* VMEbus error */ +#define TSI148_LCSR_DSTA_ABT (1<<27) /* Abort */ +#define TSI148_LCSR_DSTA_PAU (1<<26) /* Pause */ +#define TSI148_LCSR_DSTA_DON (1<<25) /* Done */ +#define TSI148_LCSR_DSTA_BSY (1<<24) /* Busy */ + +/* + * DMA Current Link Address Lower (0-1) + */ +#define TSI148_LCSR_DCLAL_M (0x3FFFFFF<<6) /* Mask */ + +/* + * DMA Source Attribute (0-1) Reg + */ +#define TSI148_LCSR_DSAT_TYP_M (3<<28) /* Source Bus Type */ +#define TSI148_LCSR_DSAT_TYP_PCI (0<<28) /* PCI Bus */ +#define TSI148_LCSR_DSAT_TYP_VME (1<<28) /* VMEbus */ +#define TSI148_LCSR_DSAT_TYP_PAT (2<<28) /* Data Pattern */ + +#define TSI148_LCSR_DSAT_PSZ (1<<25) /* Pattern Size */ +#define TSI148_LCSR_DSAT_NIN (1<<24) /* No Increment */ + +#define TSI148_LCSR_DSAT_2eSSTM_M (3<<11) /* 2eSST Trans Rate Mask */ +#define TSI148_LCSR_DSAT_2eSSTM_160 (0<<11) /* 160 MB/s */ +#define TSI148_LCSR_DSAT_2eSSTM_267 (1<<11) /* 267 MB/s */ +#define TSI148_LCSR_DSAT_2eSSTM_320 (2<<11) /* 320 MB/s */ + +#define TSI148_LCSR_DSAT_TM_M (7<<8) /* Bus Transfer Protocol Mask */ +#define TSI148_LCSR_DSAT_TM_SCT (0<<8) /* SCT */ +#define TSI148_LCSR_DSAT_TM_BLT (1<<8) /* BLT */ +#define TSI148_LCSR_DSAT_TM_MBLT (2<<8) /* MBLT */ +#define TSI148_LCSR_DSAT_TM_2eVME (3<<8) /* 2eVME */ +#define TSI148_LCSR_DSAT_TM_2eSST (4<<8) /* 2eSST */ +#define TSI148_LCSR_DSAT_TM_2eSSTB (5<<8) /* 2eSST Broadcast */ + +#define TSI148_LCSR_DSAT_DBW_M (3<<6) /* Max Data Width MASK */ +#define TSI148_LCSR_DSAT_DBW_16 (0<<6) /* 16 Bits */ +#define TSI148_LCSR_DSAT_DBW_32 (1<<6) /* 32 Bits */ + +#define TSI148_LCSR_DSAT_SUP (1<<5) /* Supervisory Mode */ +#define TSI148_LCSR_DSAT_PGM (1<<4) /* Program Mode */ + +#define TSI148_LCSR_DSAT_AMODE_M (0xf<<0) /* Address Space Mask */ +#define TSI148_LCSR_DSAT_AMODE_A16 (0<<0) /* A16 */ +#define TSI148_LCSR_DSAT_AMODE_A24 (1<<0) /* A24 */ +#define TSI148_LCSR_DSAT_AMODE_A32 (2<<0) /* A32 */ +#define TSI148_LCSR_DSAT_AMODE_A64 (4<<0) /* A64 */ +#define TSI148_LCSR_DSAT_AMODE_CRCSR (5<<0) /* CR/CSR */ +#define TSI148_LCSR_DSAT_AMODE_USER1 (8<<0) /* User1 */ +#define TSI148_LCSR_DSAT_AMODE_USER2 (9<<0) /* User2 */ +#define TSI148_LCSR_DSAT_AMODE_USER3 (0xa<<0) /* User3 */ +#define TSI148_LCSR_DSAT_AMODE_USER4 (0xb<<0) /* User4 */ + +/* + * DMA Destination Attribute Registers (0-1) + */ +#define TSI148_LCSR_DDAT_TYP_PCI (0<<28) /* Destination PCI Bus */ +#define TSI148_LCSR_DDAT_TYP_VME (1<<28) /* Destination VMEbus */ + +#define TSI148_LCSR_DDAT_2eSSTM_M (3<<11) /* 2eSST Transfer Rate Mask */ +#define TSI148_LCSR_DDAT_2eSSTM_160 (0<<11) /* 160 MB/s */ +#define TSI148_LCSR_DDAT_2eSSTM_267 (1<<11) /* 267 MB/s */ +#define TSI148_LCSR_DDAT_2eSSTM_320 (2<<11) /* 320 MB/s */ + +#define TSI148_LCSR_DDAT_TM_M (7<<8) /* Bus Transfer Protocol Mask */ +#define TSI148_LCSR_DDAT_TM_SCT (0<<8) /* SCT */ +#define TSI148_LCSR_DDAT_TM_BLT (1<<8) /* BLT */ +#define TSI148_LCSR_DDAT_TM_MBLT (2<<8) /* MBLT */ +#define TSI148_LCSR_DDAT_TM_2eVME (3<<8) /* 2eVME */ +#define TSI148_LCSR_DDAT_TM_2eSST (4<<8) /* 2eSST */ +#define TSI148_LCSR_DDAT_TM_2eSSTB (5<<8) /* 2eSST Broadcast */ + +#define TSI148_LCSR_DDAT_DBW_M (3<<6) /* Max Data Width MASK */ +#define TSI148_LCSR_DDAT_DBW_16 (0<<6) /* 16 Bits */ +#define TSI148_LCSR_DDAT_DBW_32 (1<<6) /* 32 Bits */ + +#define TSI148_LCSR_DDAT_SUP (1<<5) /* Supervisory/User Access */ +#define TSI148_LCSR_DDAT_PGM (1<<4) /* Program/Data Access */ + +#define TSI148_LCSR_DDAT_AMODE_M (0xf<<0) /* Address Space Mask */ +#define TSI148_LCSR_DDAT_AMODE_A16 (0<<0) /* A16 */ +#define TSI148_LCSR_DDAT_AMODE_A24 (1<<0) /* A24 */ +#define TSI148_LCSR_DDAT_AMODE_A32 (2<<0) /* A32 */ +#define TSI148_LCSR_DDAT_AMODE_A64 (4<<0) /* A64 */ +#define TSI148_LCSR_DDAT_AMODE_CRCSR (5<<0) /* CRC/SR */ +#define TSI148_LCSR_DDAT_AMODE_USER1 (8<<0) /* User1 */ +#define TSI148_LCSR_DDAT_AMODE_USER2 (9<<0) /* User2 */ +#define TSI148_LCSR_DDAT_AMODE_USER3 (0xa<<0) /* User3 */ +#define TSI148_LCSR_DDAT_AMODE_USER4 (0xb<<0) /* User4 */ + +/* + * DMA Next Link Address Lower + */ +#define TSI148_LCSR_DNLAL_DNLAL_M (0x3FFFFFF<<6) /* Address Mask */ +#define TSI148_LCSR_DNLAL_LLA (1<<0) /* Last Link Address Indicator */ + +/* + * DMA 2eSST Broadcast Select + */ +#define TSI148_LCSR_DBS_M (0x1FFFFF<<0) /* Mask */ + +/* + * GCSR Register Group + */ + +/* + * GCSR Control and Status Register CRG + $604 + */ +#define TSI148_GCSR_GCTRL_LRST (1<<15) /* Local Reset */ +#define TSI148_GCSR_GCTRL_SFAILEN (1<<14) /* System Fail enable */ +#define TSI148_GCSR_GCTRL_BDFAILS (1<<13) /* Board Fail Status */ +#define TSI148_GCSR_GCTRL_SCON (1<<12) /* System Copntroller */ +#define TSI148_GCSR_GCTRL_MEN (1<<11) /* Module Enable (READY) */ + +#define TSI148_GCSR_GCTRL_LMI3S (1<<7) /* Loc Monitor 3 Int Status */ +#define TSI148_GCSR_GCTRL_LMI2S (1<<6) /* Loc Monitor 2 Int Status */ +#define TSI148_GCSR_GCTRL_LMI1S (1<<5) /* Loc Monitor 1 Int Status */ +#define TSI148_GCSR_GCTRL_LMI0S (1<<4) /* Loc Monitor 0 Int Status */ +#define TSI148_GCSR_GCTRL_MBI3S (1<<3) /* Mail box 3 Int Status */ +#define TSI148_GCSR_GCTRL_MBI2S (1<<2) /* Mail box 2 Int Status */ +#define TSI148_GCSR_GCTRL_MBI1S (1<<1) /* Mail box 1 Int Status */ +#define TSI148_GCSR_GCTRL_MBI0S (1<<0) /* Mail box 0 Int Status */ + +#define TSI148_GCSR_GAP (1<<5) /* Geographic Addr Parity */ +#define TSI148_GCSR_GA_M (0x1F<<0) /* Geographic Address Mask */ + +/* + * CR/CSR Register Group + */ + +/* + * CR/CSR Bit Clear Register CRG + $FF4 + */ +#define TSI148_CRCSR_CSRBCR_LRSTC (1<<7) /* Local Reset Clear */ +#define TSI148_CRCSR_CSRBCR_SFAILC (1<<6) /* System Fail Enable Clear */ +#define TSI148_CRCSR_CSRBCR_BDFAILS (1<<5) /* Board Fail Status */ +#define TSI148_CRCSR_CSRBCR_MENC (1<<4) /* Module Enable Clear */ +#define TSI148_CRCSR_CSRBCR_BERRSC (1<<3) /* Bus Error Status Clear */ + +/* + * CR/CSR Bit Set Register CRG+$FF8 + */ +#define TSI148_CRCSR_CSRBSR_LISTS (1<<7) /* Local Reset Clear */ +#define TSI148_CRCSR_CSRBSR_SFAILS (1<<6) /* System Fail Enable Clear */ +#define TSI148_CRCSR_CSRBSR_BDFAILS (1<<5) /* Board Fail Status */ +#define TSI148_CRCSR_CSRBSR_MENS (1<<4) /* Module Enable Clear */ +#define TSI148_CRCSR_CSRBSR_BERRS (1<<3) /* Bus Error Status Clear */ + +/* + * CR/CSR Base Address Register CRG + FFC + */ +#define TSI148_CRCSR_CBAR_M (0x1F<<3) /* Mask */ + +#endif /* TSI148_H */ diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c new file mode 100644 index 000000000000..95a9f71d793e --- /dev/null +++ b/drivers/vme/vme.c @@ -0,0 +1,1517 @@ +/* + * VME Bridge Framework + * + * Author: Martyn Welch + * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. + * + * Based on work by Tom Armistead and Ajit Prem + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vme_bridge.h" + +/* Bitmask and list of registered buses both protected by common mutex */ +static unsigned int vme_bus_numbers; +static LIST_HEAD(vme_bus_list); +static DEFINE_MUTEX(vme_buses_lock); + +static void __exit vme_exit(void); +static int __init vme_init(void); + +static struct vme_dev *dev_to_vme_dev(struct device *dev) +{ + return container_of(dev, struct vme_dev, dev); +} + +/* + * Find the bridge that the resource is associated with. + */ +static struct vme_bridge *find_bridge(struct vme_resource *resource) +{ + /* Get list to search */ + switch (resource->type) { + case VME_MASTER: + return list_entry(resource->entry, struct vme_master_resource, + list)->parent; + break; + case VME_SLAVE: + return list_entry(resource->entry, struct vme_slave_resource, + list)->parent; + break; + case VME_DMA: + return list_entry(resource->entry, struct vme_dma_resource, + list)->parent; + break; + case VME_LM: + return list_entry(resource->entry, struct vme_lm_resource, + list)->parent; + break; + default: + printk(KERN_ERR "Unknown resource type\n"); + return NULL; + break; + } +} + +/* + * Allocate a contiguous block of memory for use by the driver. This is used to + * create the buffers for the slave windows. + */ +void *vme_alloc_consistent(struct vme_resource *resource, size_t size, + dma_addr_t *dma) +{ + struct vme_bridge *bridge; + + if (resource == NULL) { + printk(KERN_ERR "No resource\n"); + return NULL; + } + + bridge = find_bridge(resource); + if (bridge == NULL) { + printk(KERN_ERR "Can't find bridge\n"); + return NULL; + } + + if (bridge->parent == NULL) { + printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name); + return NULL; + } + + if (bridge->alloc_consistent == NULL) { + printk(KERN_ERR "alloc_consistent not supported by bridge %s\n", + bridge->name); + return NULL; + } + + return bridge->alloc_consistent(bridge->parent, size, dma); +} +EXPORT_SYMBOL(vme_alloc_consistent); + +/* + * Free previously allocated contiguous block of memory. + */ +void vme_free_consistent(struct vme_resource *resource, size_t size, + void *vaddr, dma_addr_t dma) +{ + struct vme_bridge *bridge; + + if (resource == NULL) { + printk(KERN_ERR "No resource\n"); + return; + } + + bridge = find_bridge(resource); + if (bridge == NULL) { + printk(KERN_ERR "Can't find bridge\n"); + return; + } + + if (bridge->parent == NULL) { + printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name); + return; + } + + if (bridge->free_consistent == NULL) { + printk(KERN_ERR "free_consistent not supported by bridge %s\n", + bridge->name); + return; + } + + bridge->free_consistent(bridge->parent, size, vaddr, dma); +} +EXPORT_SYMBOL(vme_free_consistent); + +size_t vme_get_size(struct vme_resource *resource) +{ + int enabled, retval; + unsigned long long base, size; + dma_addr_t buf_base; + u32 aspace, cycle, dwidth; + + switch (resource->type) { + case VME_MASTER: + retval = vme_master_get(resource, &enabled, &base, &size, + &aspace, &cycle, &dwidth); + + return size; + break; + case VME_SLAVE: + retval = vme_slave_get(resource, &enabled, &base, &size, + &buf_base, &aspace, &cycle); + + return size; + break; + case VME_DMA: + return 0; + break; + default: + printk(KERN_ERR "Unknown resource type\n"); + return 0; + break; + } +} +EXPORT_SYMBOL(vme_get_size); + +static int vme_check_window(u32 aspace, unsigned long long vme_base, + unsigned long long size) +{ + int retval = 0; + + switch (aspace) { + case VME_A16: + if (((vme_base + size) > VME_A16_MAX) || + (vme_base > VME_A16_MAX)) + retval = -EFAULT; + break; + case VME_A24: + if (((vme_base + size) > VME_A24_MAX) || + (vme_base > VME_A24_MAX)) + retval = -EFAULT; + break; + case VME_A32: + if (((vme_base + size) > VME_A32_MAX) || + (vme_base > VME_A32_MAX)) + retval = -EFAULT; + break; + case VME_A64: + /* + * Any value held in an unsigned long long can be used as the + * base + */ + break; + case VME_CRCSR: + if (((vme_base + size) > VME_CRCSR_MAX) || + (vme_base > VME_CRCSR_MAX)) + retval = -EFAULT; + break; + case VME_USER1: + case VME_USER2: + case VME_USER3: + case VME_USER4: + /* User Defined */ + break; + default: + printk(KERN_ERR "Invalid address space\n"); + retval = -EINVAL; + break; + } + + return retval; +} + +/* + * Request a slave image with specific attributes, return some unique + * identifier. + */ +struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address, + u32 cycle) +{ + struct vme_bridge *bridge; + struct list_head *slave_pos = NULL; + struct vme_slave_resource *allocated_image = NULL; + struct vme_slave_resource *slave_image = NULL; + struct vme_resource *resource = NULL; + + bridge = vdev->bridge; + if (bridge == NULL) { + printk(KERN_ERR "Can't find VME bus\n"); + goto err_bus; + } + + /* Loop through slave resources */ + list_for_each(slave_pos, &bridge->slave_resources) { + slave_image = list_entry(slave_pos, + struct vme_slave_resource, list); + + if (slave_image == NULL) { + printk(KERN_ERR "Registered NULL Slave resource\n"); + continue; + } + + /* Find an unlocked and compatible image */ + mutex_lock(&slave_image->mtx); + if (((slave_image->address_attr & address) == address) && + ((slave_image->cycle_attr & cycle) == cycle) && + (slave_image->locked == 0)) { + + slave_image->locked = 1; + mutex_unlock(&slave_image->mtx); + allocated_image = slave_image; + break; + } + mutex_unlock(&slave_image->mtx); + } + + /* No free image */ + if (allocated_image == NULL) + goto err_image; + + resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); + if (resource == NULL) { + printk(KERN_WARNING "Unable to allocate resource structure\n"); + goto err_alloc; + } + resource->type = VME_SLAVE; + resource->entry = &allocated_image->list; + + return resource; + +err_alloc: + /* Unlock image */ + mutex_lock(&slave_image->mtx); + slave_image->locked = 0; + mutex_unlock(&slave_image->mtx); +err_image: +err_bus: + return NULL; +} +EXPORT_SYMBOL(vme_slave_request); + +int vme_slave_set(struct vme_resource *resource, int enabled, + unsigned long long vme_base, unsigned long long size, + dma_addr_t buf_base, u32 aspace, u32 cycle) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_slave_resource *image; + int retval; + + if (resource->type != VME_SLAVE) { + printk(KERN_ERR "Not a slave resource\n"); + return -EINVAL; + } + + image = list_entry(resource->entry, struct vme_slave_resource, list); + + if (bridge->slave_set == NULL) { + printk(KERN_ERR "Function not supported\n"); + return -ENOSYS; + } + + if (!(((image->address_attr & aspace) == aspace) && + ((image->cycle_attr & cycle) == cycle))) { + printk(KERN_ERR "Invalid attributes\n"); + return -EINVAL; + } + + retval = vme_check_window(aspace, vme_base, size); + if (retval) + return retval; + + return bridge->slave_set(image, enabled, vme_base, size, buf_base, + aspace, cycle); +} +EXPORT_SYMBOL(vme_slave_set); + +int vme_slave_get(struct vme_resource *resource, int *enabled, + unsigned long long *vme_base, unsigned long long *size, + dma_addr_t *buf_base, u32 *aspace, u32 *cycle) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_slave_resource *image; + + if (resource->type != VME_SLAVE) { + printk(KERN_ERR "Not a slave resource\n"); + return -EINVAL; + } + + image = list_entry(resource->entry, struct vme_slave_resource, list); + + if (bridge->slave_get == NULL) { + printk(KERN_ERR "vme_slave_get not supported\n"); + return -EINVAL; + } + + return bridge->slave_get(image, enabled, vme_base, size, buf_base, + aspace, cycle); +} +EXPORT_SYMBOL(vme_slave_get); + +void vme_slave_free(struct vme_resource *resource) +{ + struct vme_slave_resource *slave_image; + + if (resource->type != VME_SLAVE) { + printk(KERN_ERR "Not a slave resource\n"); + return; + } + + slave_image = list_entry(resource->entry, struct vme_slave_resource, + list); + if (slave_image == NULL) { + printk(KERN_ERR "Can't find slave resource\n"); + return; + } + + /* Unlock image */ + mutex_lock(&slave_image->mtx); + if (slave_image->locked == 0) + printk(KERN_ERR "Image is already free\n"); + + slave_image->locked = 0; + mutex_unlock(&slave_image->mtx); + + /* Free up resource memory */ + kfree(resource); +} +EXPORT_SYMBOL(vme_slave_free); + +/* + * Request a master image with specific attributes, return some unique + * identifier. + */ +struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address, + u32 cycle, u32 dwidth) +{ + struct vme_bridge *bridge; + struct list_head *master_pos = NULL; + struct vme_master_resource *allocated_image = NULL; + struct vme_master_resource *master_image = NULL; + struct vme_resource *resource = NULL; + + bridge = vdev->bridge; + if (bridge == NULL) { + printk(KERN_ERR "Can't find VME bus\n"); + goto err_bus; + } + + /* Loop through master resources */ + list_for_each(master_pos, &bridge->master_resources) { + master_image = list_entry(master_pos, + struct vme_master_resource, list); + + if (master_image == NULL) { + printk(KERN_WARNING "Registered NULL master resource\n"); + continue; + } + + /* Find an unlocked and compatible image */ + spin_lock(&master_image->lock); + if (((master_image->address_attr & address) == address) && + ((master_image->cycle_attr & cycle) == cycle) && + ((master_image->width_attr & dwidth) == dwidth) && + (master_image->locked == 0)) { + + master_image->locked = 1; + spin_unlock(&master_image->lock); + allocated_image = master_image; + break; + } + spin_unlock(&master_image->lock); + } + + /* Check to see if we found a resource */ + if (allocated_image == NULL) { + printk(KERN_ERR "Can't find a suitable resource\n"); + goto err_image; + } + + resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); + if (resource == NULL) { + printk(KERN_ERR "Unable to allocate resource structure\n"); + goto err_alloc; + } + resource->type = VME_MASTER; + resource->entry = &allocated_image->list; + + return resource; + +err_alloc: + /* Unlock image */ + spin_lock(&master_image->lock); + master_image->locked = 0; + spin_unlock(&master_image->lock); +err_image: +err_bus: + return NULL; +} +EXPORT_SYMBOL(vme_master_request); + +int vme_master_set(struct vme_resource *resource, int enabled, + unsigned long long vme_base, unsigned long long size, u32 aspace, + u32 cycle, u32 dwidth) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_master_resource *image; + int retval; + + if (resource->type != VME_MASTER) { + printk(KERN_ERR "Not a master resource\n"); + return -EINVAL; + } + + image = list_entry(resource->entry, struct vme_master_resource, list); + + if (bridge->master_set == NULL) { + printk(KERN_WARNING "vme_master_set not supported\n"); + return -EINVAL; + } + + if (!(((image->address_attr & aspace) == aspace) && + ((image->cycle_attr & cycle) == cycle) && + ((image->width_attr & dwidth) == dwidth))) { + printk(KERN_WARNING "Invalid attributes\n"); + return -EINVAL; + } + + retval = vme_check_window(aspace, vme_base, size); + if (retval) + return retval; + + return bridge->master_set(image, enabled, vme_base, size, aspace, + cycle, dwidth); +} +EXPORT_SYMBOL(vme_master_set); + +int vme_master_get(struct vme_resource *resource, int *enabled, + unsigned long long *vme_base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *dwidth) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_master_resource *image; + + if (resource->type != VME_MASTER) { + printk(KERN_ERR "Not a master resource\n"); + return -EINVAL; + } + + image = list_entry(resource->entry, struct vme_master_resource, list); + + if (bridge->master_get == NULL) { + printk(KERN_WARNING "vme_master_set not supported\n"); + return -EINVAL; + } + + return bridge->master_get(image, enabled, vme_base, size, aspace, + cycle, dwidth); +} +EXPORT_SYMBOL(vme_master_get); + +/* + * Read data out of VME space into a buffer. + */ +ssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count, + loff_t offset) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_master_resource *image; + size_t length; + + if (bridge->master_read == NULL) { + printk(KERN_WARNING "Reading from resource not supported\n"); + return -EINVAL; + } + + if (resource->type != VME_MASTER) { + printk(KERN_ERR "Not a master resource\n"); + return -EINVAL; + } + + image = list_entry(resource->entry, struct vme_master_resource, list); + + length = vme_get_size(resource); + + if (offset > length) { + printk(KERN_WARNING "Invalid Offset\n"); + return -EFAULT; + } + + if ((offset + count) > length) + count = length - offset; + + return bridge->master_read(image, buf, count, offset); + +} +EXPORT_SYMBOL(vme_master_read); + +/* + * Write data out to VME space from a buffer. + */ +ssize_t vme_master_write(struct vme_resource *resource, void *buf, + size_t count, loff_t offset) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_master_resource *image; + size_t length; + + if (bridge->master_write == NULL) { + printk(KERN_WARNING "Writing to resource not supported\n"); + return -EINVAL; + } + + if (resource->type != VME_MASTER) { + printk(KERN_ERR "Not a master resource\n"); + return -EINVAL; + } + + image = list_entry(resource->entry, struct vme_master_resource, list); + + length = vme_get_size(resource); + + if (offset > length) { + printk(KERN_WARNING "Invalid Offset\n"); + return -EFAULT; + } + + if ((offset + count) > length) + count = length - offset; + + return bridge->master_write(image, buf, count, offset); +} +EXPORT_SYMBOL(vme_master_write); + +/* + * Perform RMW cycle to provided location. + */ +unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask, + unsigned int compare, unsigned int swap, loff_t offset) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_master_resource *image; + + if (bridge->master_rmw == NULL) { + printk(KERN_WARNING "Writing to resource not supported\n"); + return -EINVAL; + } + + if (resource->type != VME_MASTER) { + printk(KERN_ERR "Not a master resource\n"); + return -EINVAL; + } + + image = list_entry(resource->entry, struct vme_master_resource, list); + + return bridge->master_rmw(image, mask, compare, swap, offset); +} +EXPORT_SYMBOL(vme_master_rmw); + +void vme_master_free(struct vme_resource *resource) +{ + struct vme_master_resource *master_image; + + if (resource->type != VME_MASTER) { + printk(KERN_ERR "Not a master resource\n"); + return; + } + + master_image = list_entry(resource->entry, struct vme_master_resource, + list); + if (master_image == NULL) { + printk(KERN_ERR "Can't find master resource\n"); + return; + } + + /* Unlock image */ + spin_lock(&master_image->lock); + if (master_image->locked == 0) + printk(KERN_ERR "Image is already free\n"); + + master_image->locked = 0; + spin_unlock(&master_image->lock); + + /* Free up resource memory */ + kfree(resource); +} +EXPORT_SYMBOL(vme_master_free); + +/* + * Request a DMA controller with specific attributes, return some unique + * identifier. + */ +struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route) +{ + struct vme_bridge *bridge; + struct list_head *dma_pos = NULL; + struct vme_dma_resource *allocated_ctrlr = NULL; + struct vme_dma_resource *dma_ctrlr = NULL; + struct vme_resource *resource = NULL; + + /* XXX Not checking resource attributes */ + printk(KERN_ERR "No VME resource Attribute tests done\n"); + + bridge = vdev->bridge; + if (bridge == NULL) { + printk(KERN_ERR "Can't find VME bus\n"); + goto err_bus; + } + + /* Loop through DMA resources */ + list_for_each(dma_pos, &bridge->dma_resources) { + dma_ctrlr = list_entry(dma_pos, + struct vme_dma_resource, list); + + if (dma_ctrlr == NULL) { + printk(KERN_ERR "Registered NULL DMA resource\n"); + continue; + } + + /* Find an unlocked and compatible controller */ + mutex_lock(&dma_ctrlr->mtx); + if (((dma_ctrlr->route_attr & route) == route) && + (dma_ctrlr->locked == 0)) { + + dma_ctrlr->locked = 1; + mutex_unlock(&dma_ctrlr->mtx); + allocated_ctrlr = dma_ctrlr; + break; + } + mutex_unlock(&dma_ctrlr->mtx); + } + + /* Check to see if we found a resource */ + if (allocated_ctrlr == NULL) + goto err_ctrlr; + + resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); + if (resource == NULL) { + printk(KERN_WARNING "Unable to allocate resource structure\n"); + goto err_alloc; + } + resource->type = VME_DMA; + resource->entry = &allocated_ctrlr->list; + + return resource; + +err_alloc: + /* Unlock image */ + mutex_lock(&dma_ctrlr->mtx); + dma_ctrlr->locked = 0; + mutex_unlock(&dma_ctrlr->mtx); +err_ctrlr: +err_bus: + return NULL; +} +EXPORT_SYMBOL(vme_dma_request); + +/* + * Start new list + */ +struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource) +{ + struct vme_dma_resource *ctrlr; + struct vme_dma_list *dma_list; + + if (resource->type != VME_DMA) { + printk(KERN_ERR "Not a DMA resource\n"); + return NULL; + } + + ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); + + dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL); + if (dma_list == NULL) { + printk(KERN_ERR "Unable to allocate memory for new dma list\n"); + return NULL; + } + INIT_LIST_HEAD(&dma_list->entries); + dma_list->parent = ctrlr; + mutex_init(&dma_list->mtx); + + return dma_list; +} +EXPORT_SYMBOL(vme_new_dma_list); + +/* + * Create "Pattern" type attributes + */ +struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type) +{ + struct vme_dma_attr *attributes; + struct vme_dma_pattern *pattern_attr; + + attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); + if (attributes == NULL) { + printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); + goto err_attr; + } + + pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL); + if (pattern_attr == NULL) { + printk(KERN_ERR "Unable to allocate memory for pattern attributes\n"); + goto err_pat; + } + + attributes->type = VME_DMA_PATTERN; + attributes->private = (void *)pattern_attr; + + pattern_attr->pattern = pattern; + pattern_attr->type = type; + + return attributes; + +err_pat: + kfree(attributes); +err_attr: + return NULL; +} +EXPORT_SYMBOL(vme_dma_pattern_attribute); + +/* + * Create "PCI" type attributes + */ +struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address) +{ + struct vme_dma_attr *attributes; + struct vme_dma_pci *pci_attr; + + /* XXX Run some sanity checks here */ + + attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); + if (attributes == NULL) { + printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); + goto err_attr; + } + + pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL); + if (pci_attr == NULL) { + printk(KERN_ERR "Unable to allocate memory for pci attributes\n"); + goto err_pci; + } + + + + attributes->type = VME_DMA_PCI; + attributes->private = (void *)pci_attr; + + pci_attr->address = address; + + return attributes; + +err_pci: + kfree(attributes); +err_attr: + return NULL; +} +EXPORT_SYMBOL(vme_dma_pci_attribute); + +/* + * Create "VME" type attributes + */ +struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address, + u32 aspace, u32 cycle, u32 dwidth) +{ + struct vme_dma_attr *attributes; + struct vme_dma_vme *vme_attr; + + attributes = kmalloc( + sizeof(struct vme_dma_attr), GFP_KERNEL); + if (attributes == NULL) { + printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); + goto err_attr; + } + + vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL); + if (vme_attr == NULL) { + printk(KERN_ERR "Unable to allocate memory for vme attributes\n"); + goto err_vme; + } + + attributes->type = VME_DMA_VME; + attributes->private = (void *)vme_attr; + + vme_attr->address = address; + vme_attr->aspace = aspace; + vme_attr->cycle = cycle; + vme_attr->dwidth = dwidth; + + return attributes; + +err_vme: + kfree(attributes); +err_attr: + return NULL; +} +EXPORT_SYMBOL(vme_dma_vme_attribute); + +/* + * Free attribute + */ +void vme_dma_free_attribute(struct vme_dma_attr *attributes) +{ + kfree(attributes->private); + kfree(attributes); +} +EXPORT_SYMBOL(vme_dma_free_attribute); + +int vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, + struct vme_dma_attr *dest, size_t count) +{ + struct vme_bridge *bridge = list->parent->parent; + int retval; + + if (bridge->dma_list_add == NULL) { + printk(KERN_WARNING "Link List DMA generation not supported\n"); + return -EINVAL; + } + + if (!mutex_trylock(&list->mtx)) { + printk(KERN_ERR "Link List already submitted\n"); + return -EINVAL; + } + + retval = bridge->dma_list_add(list, src, dest, count); + + mutex_unlock(&list->mtx); + + return retval; +} +EXPORT_SYMBOL(vme_dma_list_add); + +int vme_dma_list_exec(struct vme_dma_list *list) +{ + struct vme_bridge *bridge = list->parent->parent; + int retval; + + if (bridge->dma_list_exec == NULL) { + printk(KERN_ERR "Link List DMA execution not supported\n"); + return -EINVAL; + } + + mutex_lock(&list->mtx); + + retval = bridge->dma_list_exec(list); + + mutex_unlock(&list->mtx); + + return retval; +} +EXPORT_SYMBOL(vme_dma_list_exec); + +int vme_dma_list_free(struct vme_dma_list *list) +{ + struct vme_bridge *bridge = list->parent->parent; + int retval; + + if (bridge->dma_list_empty == NULL) { + printk(KERN_WARNING "Emptying of Link Lists not supported\n"); + return -EINVAL; + } + + if (!mutex_trylock(&list->mtx)) { + printk(KERN_ERR "Link List in use\n"); + return -EINVAL; + } + + /* + * Empty out all of the entries from the dma list. We need to go to the + * low level driver as dma entries are driver specific. + */ + retval = bridge->dma_list_empty(list); + if (retval) { + printk(KERN_ERR "Unable to empty link-list entries\n"); + mutex_unlock(&list->mtx); + return retval; + } + mutex_unlock(&list->mtx); + kfree(list); + + return retval; +} +EXPORT_SYMBOL(vme_dma_list_free); + +int vme_dma_free(struct vme_resource *resource) +{ + struct vme_dma_resource *ctrlr; + + if (resource->type != VME_DMA) { + printk(KERN_ERR "Not a DMA resource\n"); + return -EINVAL; + } + + ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); + + if (!mutex_trylock(&ctrlr->mtx)) { + printk(KERN_ERR "Resource busy, can't free\n"); + return -EBUSY; + } + + if (!(list_empty(&ctrlr->pending) && list_empty(&ctrlr->running))) { + printk(KERN_WARNING "Resource still processing transfers\n"); + mutex_unlock(&ctrlr->mtx); + return -EBUSY; + } + + ctrlr->locked = 0; + + mutex_unlock(&ctrlr->mtx); + + return 0; +} +EXPORT_SYMBOL(vme_dma_free); + +void vme_irq_handler(struct vme_bridge *bridge, int level, int statid) +{ + void (*call)(int, int, void *); + void *priv_data; + + call = bridge->irq[level - 1].callback[statid].func; + priv_data = bridge->irq[level - 1].callback[statid].priv_data; + + if (call != NULL) + call(level, statid, priv_data); + else + printk(KERN_WARNING "Spurilous VME interrupt, level:%x, vector:%x\n", + level, statid); +} +EXPORT_SYMBOL(vme_irq_handler); + +int vme_irq_request(struct vme_dev *vdev, int level, int statid, + void (*callback)(int, int, void *), + void *priv_data) +{ + struct vme_bridge *bridge; + + bridge = vdev->bridge; + if (bridge == NULL) { + printk(KERN_ERR "Can't find VME bus\n"); + return -EINVAL; + } + + if ((level < 1) || (level > 7)) { + printk(KERN_ERR "Invalid interrupt level\n"); + return -EINVAL; + } + + if (bridge->irq_set == NULL) { + printk(KERN_ERR "Configuring interrupts not supported\n"); + return -EINVAL; + } + + mutex_lock(&bridge->irq_mtx); + + if (bridge->irq[level - 1].callback[statid].func) { + mutex_unlock(&bridge->irq_mtx); + printk(KERN_WARNING "VME Interrupt already taken\n"); + return -EBUSY; + } + + bridge->irq[level - 1].count++; + bridge->irq[level - 1].callback[statid].priv_data = priv_data; + bridge->irq[level - 1].callback[statid].func = callback; + + /* Enable IRQ level */ + bridge->irq_set(bridge, level, 1, 1); + + mutex_unlock(&bridge->irq_mtx); + + return 0; +} +EXPORT_SYMBOL(vme_irq_request); + +void vme_irq_free(struct vme_dev *vdev, int level, int statid) +{ + struct vme_bridge *bridge; + + bridge = vdev->bridge; + if (bridge == NULL) { + printk(KERN_ERR "Can't find VME bus\n"); + return; + } + + if ((level < 1) || (level > 7)) { + printk(KERN_ERR "Invalid interrupt level\n"); + return; + } + + if (bridge->irq_set == NULL) { + printk(KERN_ERR "Configuring interrupts not supported\n"); + return; + } + + mutex_lock(&bridge->irq_mtx); + + bridge->irq[level - 1].count--; + + /* Disable IRQ level if no more interrupts attached at this level*/ + if (bridge->irq[level - 1].count == 0) + bridge->irq_set(bridge, level, 0, 1); + + bridge->irq[level - 1].callback[statid].func = NULL; + bridge->irq[level - 1].callback[statid].priv_data = NULL; + + mutex_unlock(&bridge->irq_mtx); +} +EXPORT_SYMBOL(vme_irq_free); + +int vme_irq_generate(struct vme_dev *vdev, int level, int statid) +{ + struct vme_bridge *bridge; + + bridge = vdev->bridge; + if (bridge == NULL) { + printk(KERN_ERR "Can't find VME bus\n"); + return -EINVAL; + } + + if ((level < 1) || (level > 7)) { + printk(KERN_WARNING "Invalid interrupt level\n"); + return -EINVAL; + } + + if (bridge->irq_generate == NULL) { + printk(KERN_WARNING "Interrupt generation not supported\n"); + return -EINVAL; + } + + return bridge->irq_generate(bridge, level, statid); +} +EXPORT_SYMBOL(vme_irq_generate); + +/* + * Request the location monitor, return resource or NULL + */ +struct vme_resource *vme_lm_request(struct vme_dev *vdev) +{ + struct vme_bridge *bridge; + struct list_head *lm_pos = NULL; + struct vme_lm_resource *allocated_lm = NULL; + struct vme_lm_resource *lm = NULL; + struct vme_resource *resource = NULL; + + bridge = vdev->bridge; + if (bridge == NULL) { + printk(KERN_ERR "Can't find VME bus\n"); + goto err_bus; + } + + /* Loop through DMA resources */ + list_for_each(lm_pos, &bridge->lm_resources) { + lm = list_entry(lm_pos, + struct vme_lm_resource, list); + + if (lm == NULL) { + printk(KERN_ERR "Registered NULL Location Monitor resource\n"); + continue; + } + + /* Find an unlocked controller */ + mutex_lock(&lm->mtx); + if (lm->locked == 0) { + lm->locked = 1; + mutex_unlock(&lm->mtx); + allocated_lm = lm; + break; + } + mutex_unlock(&lm->mtx); + } + + /* Check to see if we found a resource */ + if (allocated_lm == NULL) + goto err_lm; + + resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); + if (resource == NULL) { + printk(KERN_ERR "Unable to allocate resource structure\n"); + goto err_alloc; + } + resource->type = VME_LM; + resource->entry = &allocated_lm->list; + + return resource; + +err_alloc: + /* Unlock image */ + mutex_lock(&lm->mtx); + lm->locked = 0; + mutex_unlock(&lm->mtx); +err_lm: +err_bus: + return NULL; +} +EXPORT_SYMBOL(vme_lm_request); + +int vme_lm_count(struct vme_resource *resource) +{ + struct vme_lm_resource *lm; + + if (resource->type != VME_LM) { + printk(KERN_ERR "Not a Location Monitor resource\n"); + return -EINVAL; + } + + lm = list_entry(resource->entry, struct vme_lm_resource, list); + + return lm->monitors; +} +EXPORT_SYMBOL(vme_lm_count); + +int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base, + u32 aspace, u32 cycle) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_lm_resource *lm; + + if (resource->type != VME_LM) { + printk(KERN_ERR "Not a Location Monitor resource\n"); + return -EINVAL; + } + + lm = list_entry(resource->entry, struct vme_lm_resource, list); + + if (bridge->lm_set == NULL) { + printk(KERN_ERR "vme_lm_set not supported\n"); + return -EINVAL; + } + + return bridge->lm_set(lm, lm_base, aspace, cycle); +} +EXPORT_SYMBOL(vme_lm_set); + +int vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base, + u32 *aspace, u32 *cycle) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_lm_resource *lm; + + if (resource->type != VME_LM) { + printk(KERN_ERR "Not a Location Monitor resource\n"); + return -EINVAL; + } + + lm = list_entry(resource->entry, struct vme_lm_resource, list); + + if (bridge->lm_get == NULL) { + printk(KERN_ERR "vme_lm_get not supported\n"); + return -EINVAL; + } + + return bridge->lm_get(lm, lm_base, aspace, cycle); +} +EXPORT_SYMBOL(vme_lm_get); + +int vme_lm_attach(struct vme_resource *resource, int monitor, + void (*callback)(int)) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_lm_resource *lm; + + if (resource->type != VME_LM) { + printk(KERN_ERR "Not a Location Monitor resource\n"); + return -EINVAL; + } + + lm = list_entry(resource->entry, struct vme_lm_resource, list); + + if (bridge->lm_attach == NULL) { + printk(KERN_ERR "vme_lm_attach not supported\n"); + return -EINVAL; + } + + return bridge->lm_attach(lm, monitor, callback); +} +EXPORT_SYMBOL(vme_lm_attach); + +int vme_lm_detach(struct vme_resource *resource, int monitor) +{ + struct vme_bridge *bridge = find_bridge(resource); + struct vme_lm_resource *lm; + + if (resource->type != VME_LM) { + printk(KERN_ERR "Not a Location Monitor resource\n"); + return -EINVAL; + } + + lm = list_entry(resource->entry, struct vme_lm_resource, list); + + if (bridge->lm_detach == NULL) { + printk(KERN_ERR "vme_lm_detach not supported\n"); + return -EINVAL; + } + + return bridge->lm_detach(lm, monitor); +} +EXPORT_SYMBOL(vme_lm_detach); + +void vme_lm_free(struct vme_resource *resource) +{ + struct vme_lm_resource *lm; + + if (resource->type != VME_LM) { + printk(KERN_ERR "Not a Location Monitor resource\n"); + return; + } + + lm = list_entry(resource->entry, struct vme_lm_resource, list); + + mutex_lock(&lm->mtx); + + /* XXX + * Check to see that there aren't any callbacks still attached, if + * there are we should probably be detaching them! + */ + + lm->locked = 0; + + mutex_unlock(&lm->mtx); + + kfree(resource); +} +EXPORT_SYMBOL(vme_lm_free); + +int vme_slot_get(struct vme_dev *vdev) +{ + struct vme_bridge *bridge; + + bridge = vdev->bridge; + if (bridge == NULL) { + printk(KERN_ERR "Can't find VME bus\n"); + return -EINVAL; + } + + if (bridge->slot_get == NULL) { + printk(KERN_WARNING "vme_slot_get not supported\n"); + return -EINVAL; + } + + return bridge->slot_get(bridge); +} +EXPORT_SYMBOL(vme_slot_get); + + +/* - Bridge Registration --------------------------------------------------- */ + +static void vme_dev_release(struct device *dev) +{ + kfree(dev_to_vme_dev(dev)); +} + +int vme_register_bridge(struct vme_bridge *bridge) +{ + int i; + int ret = -1; + + mutex_lock(&vme_buses_lock); + for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) { + if ((vme_bus_numbers & (1 << i)) == 0) { + vme_bus_numbers |= (1 << i); + bridge->num = i; + INIT_LIST_HEAD(&bridge->devices); + list_add_tail(&bridge->bus_list, &vme_bus_list); + ret = 0; + break; + } + } + mutex_unlock(&vme_buses_lock); + + return ret; +} +EXPORT_SYMBOL(vme_register_bridge); + +void vme_unregister_bridge(struct vme_bridge *bridge) +{ + struct vme_dev *vdev; + struct vme_dev *tmp; + + mutex_lock(&vme_buses_lock); + vme_bus_numbers &= ~(1 << bridge->num); + list_for_each_entry_safe(vdev, tmp, &bridge->devices, bridge_list) { + list_del(&vdev->drv_list); + list_del(&vdev->bridge_list); + device_unregister(&vdev->dev); + } + list_del(&bridge->bus_list); + mutex_unlock(&vme_buses_lock); +} +EXPORT_SYMBOL(vme_unregister_bridge); + +/* - Driver Registration --------------------------------------------------- */ + +static int __vme_register_driver_bus(struct vme_driver *drv, + struct vme_bridge *bridge, unsigned int ndevs) +{ + int err; + unsigned int i; + struct vme_dev *vdev; + struct vme_dev *tmp; + + for (i = 0; i < ndevs; i++) { + vdev = kzalloc(sizeof(struct vme_dev), GFP_KERNEL); + if (!vdev) { + err = -ENOMEM; + goto err_devalloc; + } + vdev->num = i; + vdev->bridge = bridge; + vdev->dev.platform_data = drv; + vdev->dev.release = vme_dev_release; + vdev->dev.parent = bridge->parent; + vdev->dev.bus = &vme_bus_type; + dev_set_name(&vdev->dev, "%s.%u-%u", drv->name, bridge->num, + vdev->num); + + err = device_register(&vdev->dev); + if (err) + goto err_reg; + + if (vdev->dev.platform_data) { + list_add_tail(&vdev->drv_list, &drv->devices); + list_add_tail(&vdev->bridge_list, &bridge->devices); + } else + device_unregister(&vdev->dev); + } + return 0; + +err_reg: + kfree(vdev); +err_devalloc: + list_for_each_entry_safe(vdev, tmp, &drv->devices, drv_list) { + list_del(&vdev->drv_list); + list_del(&vdev->bridge_list); + device_unregister(&vdev->dev); + } + return err; +} + +static int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs) +{ + struct vme_bridge *bridge; + int err = 0; + + mutex_lock(&vme_buses_lock); + list_for_each_entry(bridge, &vme_bus_list, bus_list) { + /* + * This cannot cause trouble as we already have vme_buses_lock + * and if the bridge is removed, it will have to go through + * vme_unregister_bridge() to do it (which calls remove() on + * the bridge which in turn tries to acquire vme_buses_lock and + * will have to wait). + */ + err = __vme_register_driver_bus(drv, bridge, ndevs); + if (err) + break; + } + mutex_unlock(&vme_buses_lock); + return err; +} + +int vme_register_driver(struct vme_driver *drv, unsigned int ndevs) +{ + int err; + + drv->driver.name = drv->name; + drv->driver.bus = &vme_bus_type; + INIT_LIST_HEAD(&drv->devices); + + err = driver_register(&drv->driver); + if (err) + return err; + + err = __vme_register_driver(drv, ndevs); + if (err) + driver_unregister(&drv->driver); + + return err; +} +EXPORT_SYMBOL(vme_register_driver); + +void vme_unregister_driver(struct vme_driver *drv) +{ + struct vme_dev *dev, *dev_tmp; + + mutex_lock(&vme_buses_lock); + list_for_each_entry_safe(dev, dev_tmp, &drv->devices, drv_list) { + list_del(&dev->drv_list); + list_del(&dev->bridge_list); + device_unregister(&dev->dev); + } + mutex_unlock(&vme_buses_lock); + + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL(vme_unregister_driver); + +/* - Bus Registration ------------------------------------------------------ */ + +static int vme_bus_match(struct device *dev, struct device_driver *drv) +{ + struct vme_driver *vme_drv; + + vme_drv = container_of(drv, struct vme_driver, driver); + + if (dev->platform_data == vme_drv) { + struct vme_dev *vdev = dev_to_vme_dev(dev); + + if (vme_drv->match && vme_drv->match(vdev)) + return 1; + + dev->platform_data = NULL; + } + return 0; +} + +static int vme_bus_probe(struct device *dev) +{ + int retval = -ENODEV; + struct vme_driver *driver; + struct vme_dev *vdev = dev_to_vme_dev(dev); + + driver = dev->platform_data; + + if (driver->probe != NULL) + retval = driver->probe(vdev); + + return retval; +} + +static int vme_bus_remove(struct device *dev) +{ + int retval = -ENODEV; + struct vme_driver *driver; + struct vme_dev *vdev = dev_to_vme_dev(dev); + + driver = dev->platform_data; + + if (driver->remove != NULL) + retval = driver->remove(vdev); + + return retval; +} + +struct bus_type vme_bus_type = { + .name = "vme", + .match = vme_bus_match, + .probe = vme_bus_probe, + .remove = vme_bus_remove, +}; +EXPORT_SYMBOL(vme_bus_type); + +static int __init vme_init(void) +{ + return bus_register(&vme_bus_type); +} + +static void __exit vme_exit(void) +{ + bus_unregister(&vme_bus_type); +} + +MODULE_DESCRIPTION("VME bridge driver framework"); +MODULE_AUTHOR("Martyn Welch id.num >= USER_BUS_MAX) + return 0; + return 1; + } + +The '.probe' element should contain a pointer to the probe routine. The +probe routine is passed a 'struct vme_dev' pointer as an argument. The +'struct vme_dev' structure looks like the following: + + struct vme_dev { + int num; + struct vme_bridge *bridge; + struct device dev; + struct list_head drv_list; + struct list_head bridge_list; + }; + +Here, the 'num' field refers to the sequential device ID for this specific +driver. The bridge number (or bus number) can be accessed using +dev->bridge->num. + +A function is also provided to unregister the driver from the VME core and is +usually called from the device driver's exit routine: + + void vme_unregister_driver (struct vme_driver *driver); + + +Resource management +=================== + +Once a driver has registered with the VME core the provided match routine will +be called the number of times specified during the registration. If a match +succeeds, a non-zero value should be returned. A zero return value indicates +failure. For all successful matches, the probe routine of the corresponding +driver is called. The probe routine is passed a pointer to the devices +device structure. This pointer should be saved, it will be required for +requesting VME resources. + +The driver can request ownership of one or more master windows, slave windows +and/or dma channels. Rather than allowing the device driver to request a +specific window or DMA channel (which may be used by a different driver) this +driver allows a resource to be assigned based on the required attributes of the +driver in question: + + struct vme_resource * vme_master_request(struct vme_dev *dev, + u32 aspace, u32 cycle, u32 width); + + struct vme_resource * vme_slave_request(struct vme_dev *dev, u32 aspace, + u32 cycle); + + struct vme_resource *vme_dma_request(struct vme_dev *dev, u32 route); + +For slave windows these attributes are split into the VME address spaces that +need to be accessed in 'aspace' and VME bus cycle types required in 'cycle'. +Master windows add a further set of attributes in 'width' specifying the +required data transfer widths. These attributes are defined as bitmasks and as +such any combination of the attributes can be requested for a single window, +the core will assign a window that meets the requirements, returning a pointer +of type vme_resource that should be used to identify the allocated resource +when it is used. For DMA controllers, the request function requires the +potential direction of any transfers to be provided in the route attributes. +This is typically VME-to-MEM and/or MEM-to-VME, though some hardware can +support VME-to-VME and MEM-to-MEM transfers as well as test pattern generation. +If an unallocated window fitting the requirements can not be found a NULL +pointer will be returned. + +Functions are also provided to free window allocations once they are no longer +required. These functions should be passed the pointer to the resource provided +during resource allocation: + + void vme_master_free(struct vme_resource *res); + + void vme_slave_free(struct vme_resource *res); + + void vme_dma_free(struct vme_resource *res); + + +Master windows +============== + +Master windows provide access from the local processor[s] out onto the VME bus. +The number of windows available and the available access modes is dependent on +the underlying chipset. A window must be configured before it can be used. + + +Master window configuration +--------------------------- + +Once a master window has been assigned the following functions can be used to +configure it and retrieve the current settings: + + int vme_master_set (struct vme_resource *res, int enabled, + unsigned long long base, unsigned long long size, u32 aspace, + u32 cycle, u32 width); + + int vme_master_get (struct vme_resource *res, int *enabled, + unsigned long long *base, unsigned long long *size, u32 *aspace, + u32 *cycle, u32 *width); + +The address spaces, transfer widths and cycle types are the same as described +under resource management, however some of the options are mutually exclusive. +For example, only one address space may be specified. + +These functions return 0 on success or an error code should the call fail. + + +Master window access +-------------------- + +The following functions can be used to read from and write to configured master +windows. These functions return the number of bytes copied: + + ssize_t vme_master_read(struct vme_resource *res, void *buf, + size_t count, loff_t offset); + + ssize_t vme_master_write(struct vme_resource *res, void *buf, + size_t count, loff_t offset); + +In addition to simple reads and writes, a function is provided to do a +read-modify-write transaction. This function returns the original value of the +VME bus location : + + unsigned int vme_master_rmw (struct vme_resource *res, + unsigned int mask, unsigned int compare, unsigned int swap, + loff_t offset); + +This functions by reading the offset, applying the mask. If the bits selected in +the mask match with the values of the corresponding bits in the compare field, +the value of swap is written the specified offset. + + +Slave windows +============= + +Slave windows provide devices on the VME bus access into mapped portions of the +local memory. The number of windows available and the access modes that can be +used is dependent on the underlying chipset. A window must be configured before +it can be used. + + +Slave window configuration +-------------------------- + +Once a slave window has been assigned the following functions can be used to +configure it and retrieve the current settings: + + int vme_slave_set (struct vme_resource *res, int enabled, + unsigned long long base, unsigned long long size, + dma_addr_t mem, u32 aspace, u32 cycle); + + int vme_slave_get (struct vme_resource *res, int *enabled, + unsigned long long *base, unsigned long long *size, + dma_addr_t *mem, u32 *aspace, u32 *cycle); + +The address spaces, transfer widths and cycle types are the same as described +under resource management, however some of the options are mutually exclusive. +For example, only one address space may be specified. + +These functions return 0 on success or an error code should the call fail. + + +Slave window buffer allocation +------------------------------ + +Functions are provided to allow the user to allocate and free a contiguous +buffers which will be accessible by the VME bridge. These functions do not have +to be used, other methods can be used to allocate a buffer, though care must be +taken to ensure that they are contiguous and accessible by the VME bridge: + + void * vme_alloc_consistent(struct vme_resource *res, size_t size, + dma_addr_t *mem); + + void vme_free_consistent(struct vme_resource *res, size_t size, + void *virt, dma_addr_t mem); + + +Slave window access +------------------- + +Slave windows map local memory onto the VME bus, the standard methods for +accessing memory should be used. + + +DMA channels +============ + +The VME DMA transfer provides the ability to run link-list DMA transfers. The +API introduces the concept of DMA lists. Each DMA list is a link-list which can +be passed to a DMA controller. Multiple lists can be created, extended, +executed, reused and destroyed. + + +List Management +--------------- + +The following functions are provided to create and destroy DMA lists. Execution +of a list will not automatically destroy the list, thus enabling a list to be +reused for repetitive tasks: + + struct vme_dma_list *vme_new_dma_list(struct vme_resource *res); + + int vme_dma_list_free(struct vme_dma_list *list); + + +List Population +--------------- + +An item can be added to a list using the following function ( the source and +destination attributes need to be created before calling this function, this is +covered under "Transfer Attributes"): + + int vme_dma_list_add(struct vme_dma_list *list, + struct vme_dma_attr *src, struct vme_dma_attr *dest, + size_t count); + +NOTE: The detailed attributes of the transfers source and destination + are not checked until an entry is added to a DMA list, the request + for a DMA channel purely checks the directions in which the + controller is expected to transfer data. As a result it is + possible for this call to return an error, for example if the + source or destination is in an unsupported VME address space. + +Transfer Attributes +------------------- + +The attributes for the source and destination are handled separately from adding +an item to a list. This is due to the diverse attributes required for each type +of source and destination. There are functions to create attributes for PCI, VME +and pattern sources and destinations (where appropriate): + +Pattern source: + + struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type); + +PCI source or destination: + + struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t mem); + +VME source or destination: + + struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long base, + u32 aspace, u32 cycle, u32 width); + +The following function should be used to free an attribute: + + void vme_dma_free_attribute(struct vme_dma_attr *attr); + + +List Execution +-------------- + +The following function queues a list for execution. The function will return +once the list has been executed: + + int vme_dma_list_exec(struct vme_dma_list *list); + + +Interrupts +========== + +The VME API provides functions to attach and detach callbacks to specific VME +level and status ID combinations and for the generation of VME interrupts with +specific VME level and status IDs. + + +Attaching Interrupt Handlers +---------------------------- + +The following functions can be used to attach and free a specific VME level and +status ID combination. Any given combination can only be assigned a single +callback function. A void pointer parameter is provided, the value of which is +passed to the callback function, the use of this pointer is user undefined: + + int vme_irq_request(struct vme_dev *dev, int level, int statid, + void (*callback)(int, int, void *), void *priv); + + void vme_irq_free(struct vme_dev *dev, int level, int statid); + +The callback parameters are as follows. Care must be taken in writing a callback +function, callback functions run in interrupt context: + + void callback(int level, int statid, void *priv); + + +Interrupt Generation +-------------------- + +The following function can be used to generate a VME interrupt at a given VME +level and VME status ID: + + int vme_irq_generate(struct vme_dev *dev, int level, int statid); + + +Location monitors +================= + +The VME API provides the following functionality to configure the location +monitor. + + +Location Monitor Management +--------------------------- + +The following functions are provided to request the use of a block of location +monitors and to free them after they are no longer required: + + struct vme_resource * vme_lm_request(struct vme_dev *dev); + + void vme_lm_free(struct vme_resource * res); + +Each block may provide a number of location monitors, monitoring adjacent +locations. The following function can be used to determine how many locations +are provided: + + int vme_lm_count(struct vme_resource * res); + + +Location Monitor Configuration +------------------------------ + +Once a bank of location monitors has been allocated, the following functions +are provided to configure the location and mode of the location monitor: + + int vme_lm_set(struct vme_resource *res, unsigned long long base, + u32 aspace, u32 cycle); + + int vme_lm_get(struct vme_resource *res, unsigned long long *base, + u32 *aspace, u32 *cycle); + + +Location Monitor Use +-------------------- + +The following functions allow a callback to be attached and detached from each +location monitor location. Each location monitor can monitor a number of +adjacent locations: + + int vme_lm_attach(struct vme_resource *res, int num, + void (*callback)(int)); + + int vme_lm_detach(struct vme_resource *res, int num); + +The callback function is declared as follows. + + void callback(int num); + + +Slot Detection +============== + +This function returns the slot ID of the provided bridge. + + int vme_slot_get(struct vme_dev *dev); diff --git a/drivers/vme/vme_bridge.h b/drivers/vme/vme_bridge.h new file mode 100644 index 000000000000..934949abd745 --- /dev/null +++ b/drivers/vme/vme_bridge.h @@ -0,0 +1,174 @@ +#ifndef _VME_BRIDGE_H_ +#define _VME_BRIDGE_H_ + +#define VME_CRCSR_BUF_SIZE (508*1024) +/* + * Resource structures + */ +struct vme_master_resource { + struct list_head list; + struct vme_bridge *parent; + /* + * We are likely to need to access the VME bus in interrupt context, so + * protect master routines with a spinlock rather than a mutex. + */ + spinlock_t lock; + int locked; + int number; + u32 address_attr; + u32 cycle_attr; + u32 width_attr; + struct resource bus_resource; + void __iomem *kern_base; +}; + +struct vme_slave_resource { + struct list_head list; + struct vme_bridge *parent; + struct mutex mtx; + int locked; + int number; + u32 address_attr; + u32 cycle_attr; +}; + +struct vme_dma_pattern { + u32 pattern; + u32 type; +}; + +struct vme_dma_pci { + dma_addr_t address; +}; + +struct vme_dma_vme { + unsigned long long address; + u32 aspace; + u32 cycle; + u32 dwidth; +}; + +struct vme_dma_list { + struct list_head list; + struct vme_dma_resource *parent; + struct list_head entries; + struct mutex mtx; +}; + +struct vme_dma_resource { + struct list_head list; + struct vme_bridge *parent; + struct mutex mtx; + int locked; + int number; + struct list_head pending; + struct list_head running; + u32 route_attr; +}; + +struct vme_lm_resource { + struct list_head list; + struct vme_bridge *parent; + struct mutex mtx; + int locked; + int number; + int monitors; +}; + +struct vme_bus_error { + struct list_head list; + unsigned long long address; + u32 attributes; +}; + +struct vme_callback { + void (*func)(int, int, void*); + void *priv_data; +}; + +struct vme_irq { + int count; + struct vme_callback callback[255]; +}; + +/* Allow 16 characters for name (including null character) */ +#define VMENAMSIZ 16 + +/* This structure stores all the information about one bridge + * The structure should be dynamically allocated by the driver and one instance + * of the structure should be present for each VME chip present in the system. + */ +struct vme_bridge { + char name[VMENAMSIZ]; + int num; + struct list_head master_resources; + struct list_head slave_resources; + struct list_head dma_resources; + struct list_head lm_resources; + + struct list_head vme_errors; /* List for errors generated on VME */ + struct list_head devices; /* List of devices on this bridge */ + + /* Bridge Info - XXX Move to private structure? */ + struct device *parent; /* Parent device (eg. pdev->dev for PCI) */ + void *driver_priv; /* Private pointer for the bridge driver */ + struct list_head bus_list; /* list of VME buses */ + + /* Interrupt callbacks */ + struct vme_irq irq[7]; + /* Locking for VME irq callback configuration */ + struct mutex irq_mtx; + + /* Slave Functions */ + int (*slave_get) (struct vme_slave_resource *, int *, + unsigned long long *, unsigned long long *, dma_addr_t *, + u32 *, u32 *); + int (*slave_set) (struct vme_slave_resource *, int, unsigned long long, + unsigned long long, dma_addr_t, u32, u32); + + /* Master Functions */ + int (*master_get) (struct vme_master_resource *, int *, + unsigned long long *, unsigned long long *, u32 *, u32 *, + u32 *); + int (*master_set) (struct vme_master_resource *, int, + unsigned long long, unsigned long long, u32, u32, u32); + ssize_t (*master_read) (struct vme_master_resource *, void *, size_t, + loff_t); + ssize_t (*master_write) (struct vme_master_resource *, void *, size_t, + loff_t); + unsigned int (*master_rmw) (struct vme_master_resource *, unsigned int, + unsigned int, unsigned int, loff_t); + + /* DMA Functions */ + int (*dma_list_add) (struct vme_dma_list *, struct vme_dma_attr *, + struct vme_dma_attr *, size_t); + int (*dma_list_exec) (struct vme_dma_list *); + int (*dma_list_empty) (struct vme_dma_list *); + + /* Interrupt Functions */ + void (*irq_set) (struct vme_bridge *, int, int, int); + int (*irq_generate) (struct vme_bridge *, int, int); + + /* Location monitor functions */ + int (*lm_set) (struct vme_lm_resource *, unsigned long long, u32, u32); + int (*lm_get) (struct vme_lm_resource *, unsigned long long *, u32 *, + u32 *); + int (*lm_attach) (struct vme_lm_resource *, int, void (*callback)(int)); + int (*lm_detach) (struct vme_lm_resource *, int); + + /* CR/CSR space functions */ + int (*slot_get) (struct vme_bridge *); + + /* Bridge parent interface */ + void *(*alloc_consistent)(struct device *dev, size_t size, + dma_addr_t *dma); + void (*free_consistent)(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma); +}; + +void vme_irq_handler(struct vme_bridge *, int, int); + +int vme_register_bridge(struct vme_bridge *); +void vme_unregister_bridge(struct vme_bridge *); + +#endif /* _VME_BRIDGE_H_ */ diff --git a/include/linux/vme.h b/include/linux/vme.h new file mode 100644 index 000000000000..c9d65bf14cec --- /dev/null +++ b/include/linux/vme.h @@ -0,0 +1,174 @@ +#ifndef _VME_H_ +#define _VME_H_ + +/* Resource Type */ +enum vme_resource_type { + VME_MASTER, + VME_SLAVE, + VME_DMA, + VME_LM +}; + +/* VME Address Spaces */ +#define VME_A16 0x1 +#define VME_A24 0x2 +#define VME_A32 0x4 +#define VME_A64 0x8 +#define VME_CRCSR 0x10 +#define VME_USER1 0x20 +#define VME_USER2 0x40 +#define VME_USER3 0x80 +#define VME_USER4 0x100 + +#define VME_A16_MAX 0x10000ULL +#define VME_A24_MAX 0x1000000ULL +#define VME_A32_MAX 0x100000000ULL +#define VME_A64_MAX 0x10000000000000000ULL +#define VME_CRCSR_MAX 0x1000000ULL + + +/* VME Cycle Types */ +#define VME_SCT 0x1 +#define VME_BLT 0x2 +#define VME_MBLT 0x4 +#define VME_2eVME 0x8 +#define VME_2eSST 0x10 +#define VME_2eSSTB 0x20 + +#define VME_2eSST160 0x100 +#define VME_2eSST267 0x200 +#define VME_2eSST320 0x400 + +#define VME_SUPER 0x1000 +#define VME_USER 0x2000 +#define VME_PROG 0x4000 +#define VME_DATA 0x8000 + +/* VME Data Widths */ +#define VME_D8 0x1 +#define VME_D16 0x2 +#define VME_D32 0x4 +#define VME_D64 0x8 + +/* Arbitration Scheduling Modes */ +#define VME_R_ROBIN_MODE 0x1 +#define VME_PRIORITY_MODE 0x2 + +#define VME_DMA_PATTERN (1<<0) +#define VME_DMA_PCI (1<<1) +#define VME_DMA_VME (1<<2) + +#define VME_DMA_PATTERN_BYTE (1<<0) +#define VME_DMA_PATTERN_WORD (1<<1) +#define VME_DMA_PATTERN_INCREMENT (1<<2) + +#define VME_DMA_VME_TO_MEM (1<<0) +#define VME_DMA_MEM_TO_VME (1<<1) +#define VME_DMA_VME_TO_VME (1<<2) +#define VME_DMA_MEM_TO_MEM (1<<3) +#define VME_DMA_PATTERN_TO_VME (1<<4) +#define VME_DMA_PATTERN_TO_MEM (1<<5) + +struct vme_dma_attr { + u32 type; + void *private; +}; + +struct vme_resource { + enum vme_resource_type type; + struct list_head *entry; +}; + +extern struct bus_type vme_bus_type; + +/* VME_MAX_BRIDGES comes from the type of vme_bus_numbers */ +#define VME_MAX_BRIDGES (sizeof(unsigned int)*8) +#define VME_MAX_SLOTS 32 + +#define VME_SLOT_CURRENT -1 +#define VME_SLOT_ALL -2 + +/** + * Structure representing a VME device + * @num: The device number + * @bridge: Pointer to the bridge device this device is on + * @dev: Internal device structure + * @drv_list: List of devices (per driver) + * @bridge_list: List of devices (per bridge) + */ +struct vme_dev { + int num; + struct vme_bridge *bridge; + struct device dev; + struct list_head drv_list; + struct list_head bridge_list; +}; + +struct vme_driver { + struct list_head node; + const char *name; + int (*match)(struct vme_dev *); + int (*probe)(struct vme_dev *); + int (*remove)(struct vme_dev *); + void (*shutdown)(void); + struct device_driver driver; + struct list_head devices; +}; + +void *vme_alloc_consistent(struct vme_resource *, size_t, dma_addr_t *); +void vme_free_consistent(struct vme_resource *, size_t, void *, + dma_addr_t); + +size_t vme_get_size(struct vme_resource *); + +struct vme_resource *vme_slave_request(struct vme_dev *, u32, u32); +int vme_slave_set(struct vme_resource *, int, unsigned long long, + unsigned long long, dma_addr_t, u32, u32); +int vme_slave_get(struct vme_resource *, int *, unsigned long long *, + unsigned long long *, dma_addr_t *, u32 *, u32 *); +void vme_slave_free(struct vme_resource *); + +struct vme_resource *vme_master_request(struct vme_dev *, u32, u32, u32); +int vme_master_set(struct vme_resource *, int, unsigned long long, + unsigned long long, u32, u32, u32); +int vme_master_get(struct vme_resource *, int *, unsigned long long *, + unsigned long long *, u32 *, u32 *, u32 *); +ssize_t vme_master_read(struct vme_resource *, void *, size_t, loff_t); +ssize_t vme_master_write(struct vme_resource *, void *, size_t, loff_t); +unsigned int vme_master_rmw(struct vme_resource *, unsigned int, unsigned int, + unsigned int, loff_t); +void vme_master_free(struct vme_resource *); + +struct vme_resource *vme_dma_request(struct vme_dev *, u32); +struct vme_dma_list *vme_new_dma_list(struct vme_resource *); +struct vme_dma_attr *vme_dma_pattern_attribute(u32, u32); +struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t); +struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long, u32, u32, u32); +void vme_dma_free_attribute(struct vme_dma_attr *); +int vme_dma_list_add(struct vme_dma_list *, struct vme_dma_attr *, + struct vme_dma_attr *, size_t); +int vme_dma_list_exec(struct vme_dma_list *); +int vme_dma_list_free(struct vme_dma_list *); +int vme_dma_free(struct vme_resource *); + +int vme_irq_request(struct vme_dev *, int, int, + void (*callback)(int, int, void *), void *); +void vme_irq_free(struct vme_dev *, int, int); +int vme_irq_generate(struct vme_dev *, int, int); + +struct vme_resource *vme_lm_request(struct vme_dev *); +int vme_lm_count(struct vme_resource *); +int vme_lm_set(struct vme_resource *, unsigned long long, u32, u32); +int vme_lm_get(struct vme_resource *, unsigned long long *, u32 *, u32 *); +int vme_lm_attach(struct vme_resource *, int, void (*callback)(int)); +int vme_lm_detach(struct vme_resource *, int); +void vme_lm_free(struct vme_resource *); + +int vme_slot_get(struct vme_dev *); + +int vme_register_driver(struct vme_driver *, unsigned int); +void vme_unregister_driver(struct vme_driver *); + + +#endif /* _VME_H_ */ + -- cgit v1.2.3-71-gd317 From 7cbb753701d11f3c71e8543e1ae0fc0772edac06 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 26 Apr 2012 13:35:01 +0200 Subject: staging:iio: Streamline API function naming Currently we use two different naming schemes in the IIO API, iio_verb_object and iio_object_verb. E.g iio_device_register and iio_allocate_device. This patches renames instances of the later to the former. The patch also renames allocate to alloc as this seems to be the preferred form throughout the kernel. In particular the following renames are performed by the patch: iio_put_device -> iio_device_put iio_allocate_device -> iio_device_alloc iio_free_device -> iio_device_free iio_get_trigger -> iio_trigger_get iio_put_trigger -> iio_trigger_put iio_allocate_trigger -> iio_trigger_alloc iio_free_trigger -> iio_trigger_free The conversion was done with the following coccinelle patch with manual fixes to comments and documentation. @@ @@ -iio_put_device +iio_device_put @@ @@ -iio_allocate_device +iio_device_alloc @@ @@ -iio_free_device +iio_device_free @@ @@ -iio_get_trigger +iio_trigger_get @@ @@ -iio_put_trigger +iio_trigger_put @@ @@ -iio_allocate_trigger +iio_trigger_alloc @@ @@ -iio_free_trigger +iio_trigger_free Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/industrialio-core.c | 8 ++++---- drivers/iio/industrialio-trigger.c | 14 +++++++------- drivers/staging/iio/Documentation/device.txt | 4 ++-- drivers/staging/iio/Documentation/trigger.txt | 2 +- drivers/staging/iio/accel/adis16201_core.c | 6 +++--- drivers/staging/iio/accel/adis16201_trigger.c | 6 +++--- drivers/staging/iio/accel/adis16203_core.c | 6 +++--- drivers/staging/iio/accel/adis16203_trigger.c | 6 +++--- drivers/staging/iio/accel/adis16204_core.c | 6 +++--- drivers/staging/iio/accel/adis16204_trigger.c | 6 +++--- drivers/staging/iio/accel/adis16209_core.c | 6 +++--- drivers/staging/iio/accel/adis16209_trigger.c | 6 +++--- drivers/staging/iio/accel/adis16220_core.c | 6 +++--- drivers/staging/iio/accel/adis16240_core.c | 6 +++--- drivers/staging/iio/accel/adis16240_trigger.c | 6 +++--- drivers/staging/iio/accel/kxsd9.c | 6 +++--- drivers/staging/iio/accel/lis3l02dq_core.c | 6 +++--- drivers/staging/iio/accel/lis3l02dq_ring.c | 6 +++--- drivers/staging/iio/accel/sca3000_core.c | 6 +++--- drivers/staging/iio/adc/ad7192.c | 10 +++++----- drivers/staging/iio/adc/ad7280a.c | 6 +++--- drivers/staging/iio/adc/ad7291.c | 6 +++--- drivers/staging/iio/adc/ad7298_core.c | 6 +++--- drivers/staging/iio/adc/ad7476_core.c | 6 +++--- drivers/staging/iio/adc/ad7606_core.c | 6 +++--- drivers/staging/iio/adc/ad7780.c | 6 +++--- drivers/staging/iio/adc/ad7793.c | 12 ++++++------ drivers/staging/iio/adc/ad7816.c | 6 +++--- drivers/staging/iio/adc/ad7887_core.c | 6 +++--- drivers/staging/iio/adc/ad799x_core.c | 6 +++--- drivers/staging/iio/adc/adt7310.c | 6 +++--- drivers/staging/iio/adc/adt7410.c | 6 +++--- drivers/staging/iio/adc/lpc32xx_adc.c | 6 +++--- drivers/staging/iio/adc/max1363_core.c | 6 +++--- drivers/staging/iio/adc/spear_adc.c | 6 +++--- drivers/staging/iio/addac/adt7316.c | 6 +++--- drivers/staging/iio/cdc/ad7150.c | 6 +++--- drivers/staging/iio/cdc/ad7152.c | 6 +++--- drivers/staging/iio/cdc/ad7746.c | 6 +++--- drivers/staging/iio/dac/ad5064.c | 6 +++--- drivers/staging/iio/dac/ad5360.c | 6 +++--- drivers/staging/iio/dac/ad5380.c | 6 +++--- drivers/staging/iio/dac/ad5421.c | 6 +++--- drivers/staging/iio/dac/ad5446.c | 6 +++--- drivers/staging/iio/dac/ad5504.c | 6 +++--- drivers/staging/iio/dac/ad5624r_spi.c | 6 +++--- drivers/staging/iio/dac/ad5686.c | 6 +++--- drivers/staging/iio/dac/ad5764.c | 6 +++--- drivers/staging/iio/dac/ad5791.c | 6 +++--- drivers/staging/iio/dac/max517.c | 6 +++--- drivers/staging/iio/dds/ad5930.c | 6 +++--- drivers/staging/iio/dds/ad9832.c | 6 +++--- drivers/staging/iio/dds/ad9834.c | 6 +++--- drivers/staging/iio/dds/ad9850.c | 6 +++--- drivers/staging/iio/dds/ad9852.c | 6 +++--- drivers/staging/iio/dds/ad9910.c | 6 +++--- drivers/staging/iio/dds/ad9951.c | 6 +++--- drivers/staging/iio/gyro/adis16060_core.c | 6 +++--- drivers/staging/iio/gyro/adis16080_core.c | 6 +++--- drivers/staging/iio/gyro/adis16130_core.c | 6 +++--- drivers/staging/iio/gyro/adis16260_core.c | 6 +++--- drivers/staging/iio/gyro/adis16260_trigger.c | 6 +++--- drivers/staging/iio/gyro/adxrs450_core.c | 6 +++--- drivers/staging/iio/iio_simple_dummy.c | 6 +++--- drivers/staging/iio/impedance-analyzer/ad5933.c | 6 +++--- drivers/staging/iio/imu/adis16400_core.c | 6 +++--- drivers/staging/iio/imu/adis16400_trigger.c | 6 +++--- drivers/staging/iio/light/isl29018.c | 6 +++--- drivers/staging/iio/light/isl29028.c | 6 +++--- drivers/staging/iio/light/tsl2563.c | 6 +++--- drivers/staging/iio/light/tsl2583.c | 6 +++--- drivers/staging/iio/light/tsl2x7x_core.c | 6 +++--- drivers/staging/iio/magnetometer/ak8975.c | 6 +++--- drivers/staging/iio/magnetometer/hmc5843.c | 6 +++--- drivers/staging/iio/meter/ade7753.c | 6 +++--- drivers/staging/iio/meter/ade7754.c | 6 +++--- drivers/staging/iio/meter/ade7758_core.c | 6 +++--- drivers/staging/iio/meter/ade7758_trigger.c | 6 +++--- drivers/staging/iio/meter/ade7759.c | 6 +++--- drivers/staging/iio/meter/ade7854-i2c.c | 4 ++-- drivers/staging/iio/meter/ade7854-spi.c | 4 ++-- drivers/staging/iio/meter/ade7854.c | 4 ++-- drivers/staging/iio/resolver/ad2s1200.c | 6 +++--- drivers/staging/iio/resolver/ad2s1210.c | 6 +++--- drivers/staging/iio/resolver/ad2s90.c | 6 +++--- drivers/staging/iio/trigger/iio-trig-bfin-timer.c | 6 +++--- drivers/staging/iio/trigger/iio-trig-gpio.c | 6 +++--- drivers/staging/iio/trigger/iio-trig-periodic-rtc.c | 4 ++-- drivers/staging/iio/trigger/iio-trig-sysfs.c | 6 +++--- include/linux/iio/iio.h | 12 ++++++------ include/linux/iio/trigger.h | 8 ++++---- 91 files changed, 280 insertions(+), 280 deletions(-) (limited to 'include/linux') diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index dd1a6a2e81c0..e8e280d64295 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -737,7 +737,7 @@ static struct device_type iio_dev_type = { .release = iio_dev_release, }; -struct iio_dev *iio_allocate_device(int sizeof_priv) +struct iio_dev *iio_device_alloc(int sizeof_priv) { struct iio_dev *dev; size_t alloc_size; @@ -773,16 +773,16 @@ struct iio_dev *iio_allocate_device(int sizeof_priv) return dev; } -EXPORT_SYMBOL(iio_allocate_device); +EXPORT_SYMBOL(iio_device_alloc); -void iio_free_device(struct iio_dev *dev) +void iio_device_free(struct iio_dev *dev) { if (dev) { ida_simple_remove(&iio_ida, dev->id); kfree(dev); } } -EXPORT_SYMBOL(iio_free_device); +EXPORT_SYMBOL(iio_device_free); /** * iio_chrdev_open() - chrdev file open for buffer access and ioctls diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 03fee2e097ca..1dbd7b86a694 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -360,9 +360,9 @@ static ssize_t iio_trigger_write_current(struct device *dev, indio_dev->trig = trig; if (oldtrig && indio_dev->trig != oldtrig) - iio_put_trigger(oldtrig); + iio_trigger_put(oldtrig); if (indio_dev->trig) - iio_get_trigger(indio_dev->trig); + iio_trigger_get(indio_dev->trig); return len; } @@ -426,7 +426,7 @@ static void iio_trig_subirqunmask(struct irq_data *d) trig->subirqs[d->irq - trig->subirq_base].enabled = true; } -struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) +struct iio_trigger *iio_trigger_alloc(const char *fmt, ...) { va_list vargs; struct iio_trigger *trig; @@ -472,14 +472,14 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) } return trig; } -EXPORT_SYMBOL(iio_allocate_trigger); +EXPORT_SYMBOL(iio_trigger_alloc); -void iio_free_trigger(struct iio_trigger *trig) +void iio_trigger_free(struct iio_trigger *trig) { if (trig) put_device(&trig->dev); } -EXPORT_SYMBOL(iio_free_trigger); +EXPORT_SYMBOL(iio_trigger_free); void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { @@ -491,7 +491,7 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) { /* Clean up and associated but not attached triggers references */ if (indio_dev->trig) - iio_put_trigger(indio_dev->trig); + iio_trigger_put(indio_dev->trig); } int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) diff --git a/drivers/staging/iio/Documentation/device.txt b/drivers/staging/iio/Documentation/device.txt index 8926f2448cc9..0338c7cd0a8b 100644 --- a/drivers/staging/iio/Documentation/device.txt +++ b/drivers/staging/iio/Documentation/device.txt @@ -8,7 +8,7 @@ The crucial structure for device drivers in iio is iio_dev. First allocate one using: -struct iio_dev *indio_dev = iio_allocate_device(sizeof(struct chip_state)); +struct iio_dev *indio_dev = iio_device_alloc(sizeof(struct chip_state)); where chip_state is a structure of local state data for this instance of the chip. @@ -78,4 +78,4 @@ be registered afterwards (otherwise the whole parentage of devices gets confused) On remove, iio_device_unregister(indio_dev) will remove the device from -the core, and iio_free_device will clean up. +the core, and iio_device_free will clean up. diff --git a/drivers/staging/iio/Documentation/trigger.txt b/drivers/staging/iio/Documentation/trigger.txt index fc2012ebc100..75cc37ff1ed0 100644 --- a/drivers/staging/iio/Documentation/trigger.txt +++ b/drivers/staging/iio/Documentation/trigger.txt @@ -5,7 +5,7 @@ an IIO device. Whilst this can create device specific complexities such triggers are registered with the core in the same way as stand-alone triggers. -struct iio_trig *trig = iio_allocate_trigger("", ...); +struct iio_trig *trig = iio_trigger_alloc("", ...); allocates a trigger structure. The key elements to then fill in within a driver are: diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 9dce7b8d38a5..62667803c5a7 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -532,7 +532,7 @@ static int __devinit adis16201_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -587,7 +587,7 @@ error_uninitialize_ring: error_unreg_ring_funcs: adis16201_unconfigure_ring(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -600,7 +600,7 @@ static int adis16201_remove(struct spi_device *spi) adis16201_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16201_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c index da687e01cc45..96fdabbac201 100644 --- a/drivers/staging/iio/accel/adis16201_trigger.c +++ b/drivers/staging/iio/accel/adis16201_trigger.c @@ -29,7 +29,7 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev) int ret; struct adis16201_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("adis16201-dev%d", indio_dev->id); + st->trig = iio_trigger_alloc("adis16201-dev%d", indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; goto error_ret; @@ -56,7 +56,7 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -67,5 +67,5 @@ void adis16201_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(state->trig); free_irq(state->us->irq, state->trig); - iio_free_trigger(state->trig); + iio_trigger_free(state->trig); } diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index cf1a0e565673..42d7eea06d1a 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -469,7 +469,7 @@ static int __devinit adis16203_probe(struct spi_device *spi) struct adis16203_state *st; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -523,7 +523,7 @@ error_uninitialize_ring: error_unreg_ring_funcs: adis16203_unconfigure_ring(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -536,7 +536,7 @@ static int adis16203_remove(struct spi_device *spi) adis16203_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16203_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c index 1e1b981e1581..b8a04073d6d7 100644 --- a/drivers/staging/iio/accel/adis16203_trigger.c +++ b/drivers/staging/iio/accel/adis16203_trigger.c @@ -29,7 +29,7 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev) int ret; struct adis16203_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("adis16203-dev%d", indio_dev->id); + st->trig = iio_trigger_alloc("adis16203-dev%d", indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; goto error_ret; @@ -58,7 +58,7 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -69,5 +69,5 @@ void adis16203_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 2a15d71c02c7..eacda583313a 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -545,7 +545,7 @@ static int __devinit adis16204_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -598,7 +598,7 @@ error_uninitialize_ring: error_unreg_ring_funcs: adis16204_unconfigure_ring(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -611,7 +611,7 @@ static int adis16204_remove(struct spi_device *spi) adis16204_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16204_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c index e6f2937ade7c..408a1682368e 100644 --- a/drivers/staging/iio/accel/adis16204_trigger.c +++ b/drivers/staging/iio/accel/adis16204_trigger.c @@ -29,7 +29,7 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev) int ret; struct adis16204_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("adis16204-dev%d", indio_dev->id); + st->trig = iio_trigger_alloc("adis16204-dev%d", indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; goto error_ret; @@ -58,7 +58,7 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -69,5 +69,5 @@ void adis16204_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(state->trig); free_irq(state->us->irq, state->trig); - iio_free_trigger(state->trig); + iio_trigger_free(state->trig); } diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index cad411340f1d..8e8dbe6b707d 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -544,7 +544,7 @@ static int __devinit adis16209_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -597,7 +597,7 @@ error_uninitialize_ring: error_unreg_ring_funcs: adis16209_unconfigure_ring(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -612,7 +612,7 @@ static int adis16209_remove(struct spi_device *spi) adis16209_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16209_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c index 5f5dbed447d7..2ad93dcaf40d 100644 --- a/drivers/staging/iio/accel/adis16209_trigger.c +++ b/drivers/staging/iio/accel/adis16209_trigger.c @@ -38,7 +38,7 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev) int ret; struct adis16209_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("adis16209-dev%d", indio_dev->id); + st->trig = iio_trigger_alloc("adis16209-dev%d", indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; goto error_ret; @@ -66,7 +66,7 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -77,5 +77,5 @@ void adis16209_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index c86a3db6d747..e8c513db2d23 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -634,7 +634,7 @@ static int __devinit adis16220_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -685,7 +685,7 @@ error_rm_accel_bin: error_unregister_dev: iio_device_unregister(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -700,7 +700,7 @@ static int adis16220_remove(struct spi_device *spi) sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); iio_device_unregister(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index fcc2c19f69dd..f043bbdce36f 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -578,7 +578,7 @@ static int __devinit adis16240_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -631,7 +631,7 @@ error_uninitialize_ring: error_unreg_ring_funcs: adis16240_unconfigure_ring(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -647,7 +647,7 @@ static int adis16240_remove(struct spi_device *spi) adis16240_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16240_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c index 53eda35b37e7..fa90a22b143e 100644 --- a/drivers/staging/iio/accel/adis16240_trigger.c +++ b/drivers/staging/iio/accel/adis16240_trigger.c @@ -38,7 +38,7 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev) int ret; struct adis16240_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("adis16240-dev%d", indio_dev->id); + st->trig = iio_trigger_alloc("adis16240-dev%d", indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; goto error_ret; @@ -67,7 +67,7 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -78,5 +78,5 @@ void adis16240_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c index 329239011d47..8cf7cd943c90 100644 --- a/drivers/staging/iio/accel/kxsd9.c +++ b/drivers/staging/iio/accel/kxsd9.c @@ -228,7 +228,7 @@ static int __devinit kxsd9_probe(struct spi_device *spi) struct kxsd9_state *st; int ret = 0; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -256,7 +256,7 @@ static int __devinit kxsd9_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -264,7 +264,7 @@ error_ret: static int __devexit kxsd9_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index bbef0be3d81e..a7780439af15 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -680,7 +680,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) struct lis3l02dq_state *st; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof *st); + indio_dev = iio_device_alloc(sizeof *st); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -748,7 +748,7 @@ error_uninitialize_buffer: error_unreg_buffer_funcs: lis3l02dq_unconfigure_buffer(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -803,7 +803,7 @@ static int lis3l02dq_remove(struct spi_device *spi) iio_buffer_unregister(indio_dev); lis3l02dq_unconfigure_buffer(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); err_ret: return ret; } diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index c8b8164eef77..9306f934e333 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -286,7 +286,7 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) int ret; struct lis3l02dq_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("lis3l02dq-dev%d", indio_dev->id); + st->trig = iio_trigger_alloc("lis3l02dq-dev%d", indio_dev->id); if (!st->trig) { ret = -ENOMEM; goto error_ret; @@ -302,7 +302,7 @@ int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) return 0; error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -312,7 +312,7 @@ void lis3l02dq_remove_trigger(struct iio_dev *indio_dev) struct lis3l02dq_state *st = iio_priv(indio_dev); iio_trigger_unregister(st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev) diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 2ee5eb060932..3c5aea5efb2b 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1145,7 +1145,7 @@ static int __devinit sca3000_probe(struct spi_device *spi) struct sca3000_state *st; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -1209,7 +1209,7 @@ error_unregister_ring: error_unregister_dev: iio_device_unregister(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -1247,7 +1247,7 @@ static int sca3000_remove(struct spi_device *spi) iio_device_unregister(indio_dev); iio_buffer_unregister(indio_dev); sca3000_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 14f983450d7f..7b44705acb7e 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -604,7 +604,7 @@ static int ad7192_probe_trigger(struct iio_dev *indio_dev) struct ad7192_state *st = iio_priv(indio_dev); int ret; - st->trig = iio_allocate_trigger("%s-dev%d", + st->trig = iio_trigger_alloc("%s-dev%d", spi_get_device_id(st->spi)->name, indio_dev->id); if (st->trig == NULL) { @@ -637,7 +637,7 @@ static int ad7192_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->spi->irq, indio_dev); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -648,7 +648,7 @@ static void ad7192_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->spi->irq, indio_dev); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } static ssize_t ad7192_read_frequency(struct device *dev, @@ -1024,7 +1024,7 @@ static int __devinit ad7192_probe(struct spi_device *spi) return -ENODEV; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -1105,7 +1105,7 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index d72780f91031..9c3b66f37395 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -839,7 +839,7 @@ static int __devinit ad7280_probe(struct spi_device *spi) int ret; const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890}; const unsigned short nAVG[4] = {1, 2, 4, 8}; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -945,7 +945,7 @@ error_free_channels: kfree(st->channels); error_free_device: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -964,7 +964,7 @@ static int __devexit ad7280_remove(struct spi_device *spi) kfree(st->channels); kfree(st->iio_attr); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index b8e4fe6c0c50..a987c2011ec1 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -587,7 +587,7 @@ static int __devinit ad7291_probe(struct i2c_client *client, struct iio_dev *indio_dev; int ret = 0, voltage_uv = 0; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -669,7 +669,7 @@ error_put_reg: if (!IS_ERR(chip->reg)) regulator_put(chip->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -689,7 +689,7 @@ static int __devexit ad7291_remove(struct i2c_client *client) regulator_put(chip->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c index 974a8e3ef26a..c90f2b3e661f 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -179,7 +179,7 @@ static int __devinit ad7298_probe(struct spi_device *spi) struct ad7298_platform_data *pdata = spi->dev.platform_data; struct ad7298_state *st; int ret; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -252,7 +252,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -269,7 +269,7 @@ static int __devexit ad7298_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index 1241b9fadbf7..be1c260cf165 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -128,7 +128,7 @@ static int __devinit ad7476_probe(struct spi_device *spi) struct iio_dev *indio_dev; int ret, voltage_uv = 0; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -198,7 +198,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -216,7 +216,7 @@ static int ad7476_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 9c540643576b..f82d36c603c1 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -461,7 +461,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, struct ad7606_platform_data *pdata = dev->platform_data; struct ad7606_state *st; int ret; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; @@ -560,7 +560,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ERR_PTR(ret); } @@ -580,7 +580,7 @@ int ad7606_remove(struct iio_dev *indio_dev, int irq) } ad7606_free_gpios(st); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index a8e661e5e4e6..1ece2ac8de56 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -187,7 +187,7 @@ static int __devinit ad7780_probe(struct spi_device *spi) return -ENODEV; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -265,7 +265,7 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -282,7 +282,7 @@ static int ad7780_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 3a7d1a7b4e05..8ffdd800bcd9 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -469,7 +469,7 @@ static int ad7793_probe_trigger(struct iio_dev *indio_dev) struct ad7793_state *st = iio_priv(indio_dev); int ret; - st->trig = iio_allocate_trigger("%s-dev%d", + st->trig = iio_trigger_alloc("%s-dev%d", spi_get_device_id(st->spi)->name, indio_dev->id); if (st->trig == NULL) { @@ -503,7 +503,7 @@ static int ad7793_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->spi->irq, indio_dev); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -514,7 +514,7 @@ static void ad7793_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->spi->irq, indio_dev); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19, @@ -904,7 +904,7 @@ static int __devinit ad7793_probe(struct spi_device *spi) return -ENODEV; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -988,7 +988,7 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -1008,7 +1008,7 @@ static int ad7793_remove(struct spi_device *spi) regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 586f6c2425e2..c97da5b66435 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -354,7 +354,7 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev) return -EINVAL; } - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -426,7 +426,7 @@ error_free_gpio_convert: error_free_gpio_rdwr: gpio_free(chip->rdwr_pin); error_free_device: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -443,7 +443,7 @@ static int __devexit ad7816_remove(struct spi_device *spi_dev) gpio_free(chip->busy_pin); gpio_free(chip->convert_pin); gpio_free(chip->rdwr_pin); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index fef916998f24..7186074deeb3 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -106,7 +106,7 @@ static int __devinit ad7887_probe(struct spi_device *spi) struct ad7887_platform_data *pdata = spi->dev.platform_data; struct ad7887_state *st; int ret, voltage_uv = 0; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -222,7 +222,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -239,7 +239,7 @@ static int ad7887_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 561ae17ec7cc..cc637b5a36e5 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -847,7 +847,7 @@ static int __devinit ad799x_probe(struct i2c_client *client, int ret; struct ad799x_platform_data *pdata = client->dev.platform_data; struct ad799x_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -920,7 +920,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -940,7 +940,7 @@ static __devexit int ad799x_remove(struct i2c_client *client) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c index 223aea5952df..ba4e571a112a 100644 --- a/drivers/staging/iio/adc/adt7310.c +++ b/drivers/staging/iio/adc/adt7310.c @@ -753,7 +753,7 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev) unsigned long *adt7310_platform_data = spi_dev->dev.platform_data; unsigned long irq_flags; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -833,7 +833,7 @@ error_unreg_int_irq: error_unreg_ct_irq: free_irq(spi_dev->irq, indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -849,7 +849,7 @@ static int __devexit adt7310_remove(struct spi_device *spi_dev) free_irq(adt7310_platform_data[0], indio_dev); if (spi_dev->irq) free_irq(spi_dev->irq, indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index dab4a5abff8a..2d4b5c6cd8fc 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -721,7 +721,7 @@ static int __devinit adt7410_probe(struct i2c_client *client, int ret = 0; unsigned long *adt7410_platform_data = client->dev.platform_data; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -797,7 +797,7 @@ error_unreg_int_irq: error_unreg_ct_irq: free_irq(client->irq, indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -812,7 +812,7 @@ static int __devexit adt7410_remove(struct i2c_client *client) free_irq(adt7410_platform_data[0], indio_dev); if (client->irq) free_irq(client->irq, indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c index 0ddd91712f44..9690306d1f8f 100644 --- a/drivers/staging/iio/adc/lpc32xx_adc.c +++ b/drivers/staging/iio/adc/lpc32xx_adc.c @@ -141,7 +141,7 @@ static int __devinit lpc32xx_adc_probe(struct platform_device *pdev) goto errout1; } - iodev = iio_allocate_device(sizeof(struct lpc32xx_adc_info)); + iodev = iio_device_alloc(sizeof(struct lpc32xx_adc_info)); if (!iodev) { dev_err(&pdev->dev, "failed allocating iio device\n"); retval = -ENOMEM; @@ -202,7 +202,7 @@ errout4: errout3: iounmap(info->adc_base); errout2: - iio_free_device(iodev); + iio_device_free(iodev); errout1: return retval; } @@ -218,7 +218,7 @@ static int __devexit lpc32xx_adc_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); clk_put(info->clk); iounmap(info->adc_base); - iio_free_device(iodev); + iio_device_free(iodev); return 0; } diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 7ab871c8aab5..572a500d6e51 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -1287,7 +1287,7 @@ static int __devinit max1363_probe(struct i2c_client *client, if (ret) goto error_put_reg; - indio_dev = iio_allocate_device(sizeof(struct max1363_state)); + indio_dev = iio_device_alloc(sizeof(struct max1363_state)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_disable_reg; @@ -1358,7 +1358,7 @@ error_free_available_scan_masks: error_unregister_map: iio_map_array_unregister(indio_dev, client->dev.platform_data); error_free_device: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_disable_reg: regulator_disable(reg); error_put_reg: @@ -1384,7 +1384,7 @@ static int max1363_remove(struct i2c_client *client) regulator_put(reg); } iio_map_array_unregister(indio_dev, client->dev.platform_data); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c index 2b4e1eb8eab1..8c6013f0a4b3 100644 --- a/drivers/staging/iio/adc/spear_adc.c +++ b/drivers/staging/iio/adc/spear_adc.c @@ -300,7 +300,7 @@ static int __devinit spear_adc_probe(struct platform_device *pdev) int ret = -ENODEV; int irq; - iodev = iio_allocate_device(sizeof(struct spear_adc_info)); + iodev = iio_device_alloc(sizeof(struct spear_adc_info)); if (!iodev) { dev_err(dev, "failed allocating iio device\n"); ret = -ENOMEM; @@ -404,7 +404,7 @@ errout4: errout3: iounmap(info->adc_base_spear6xx); errout2: - iio_free_device(iodev); + iio_device_free(iodev); errout1: return ret; } @@ -420,7 +420,7 @@ static int __devexit spear_adc_remove(struct platform_device *pdev) clk_unprepare(info->clk); clk_put(info->clk); iounmap(info->adc_base_spear6xx); - iio_free_device(iodev); + iio_device_free(iodev); return 0; } diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index f469ab3cc7b9..5aba804237ce 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -2133,7 +2133,7 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, unsigned short *adt7316_platform_data = dev->platform_data; int ret = 0; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -2210,7 +2210,7 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, error_unreg_irq: free_irq(chip->bus.irq, indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -2224,7 +2224,7 @@ int __devexit adt7316_remove(struct device *dev) iio_device_unregister(indio_dev); if (chip->bus.irq) free_irq(chip->bus.irq, indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index c0ccbc524c6e..14470764fa0b 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -558,7 +558,7 @@ static int __devinit ad7150_probe(struct i2c_client *client, struct ad7150_chip_info *chip; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -621,7 +621,7 @@ error_free_irq: if (client->irq) free_irq(client->irq, indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -637,7 +637,7 @@ static int __devexit ad7150_remove(struct i2c_client *client) if (client->dev.platform_data) free_irq(*(unsigned int *)client->dev.platform_data, indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index ea403596c958..195d90748633 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -481,7 +481,7 @@ static int __devinit ad7152_probe(struct i2c_client *client, struct ad7152_chip_info *chip; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -513,7 +513,7 @@ static int __devinit ad7152_probe(struct i2c_client *client, return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -523,7 +523,7 @@ static int __devexit ad7152_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 74a889a6d899..e936831d5c96 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -703,7 +703,7 @@ static int __devinit ad7746_probe(struct i2c_client *client, int ret = 0; unsigned char regval = 0; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -763,7 +763,7 @@ static int __devinit ad7746_probe(struct i2c_client *client, return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -773,7 +773,7 @@ static int __devexit ad7746_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index c0fad4fd13fa..bce641a1cf82 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -443,7 +443,7 @@ static int __devinit ad5064_probe(struct spi_device *spi) unsigned int i; int ret; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -500,7 +500,7 @@ error_free_reg: if (!st->use_internal_vref) regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); error_free: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -518,7 +518,7 @@ static int __devexit ad5064_remove(struct spi_device *spi) regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c index 0978dd2891b9..26cac42dcca9 100644 --- a/drivers/staging/iio/dac/ad5360.c +++ b/drivers/staging/iio/dac/ad5360.c @@ -465,7 +465,7 @@ static int __devinit ad5360_probe(struct spi_device *spi) unsigned int i; int ret; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { dev_err(&spi->dev, "Failed to allocate iio device\n"); return -ENOMEM; @@ -520,7 +520,7 @@ error_free_reg: error_free_channels: kfree(indio_dev->channels); error_free: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -537,7 +537,7 @@ static int __devexit ad5360_remove(struct spi_device *spi) regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c index aa077e676dfe..4afb099fa5dd 100644 --- a/drivers/staging/iio/dac/ad5380.c +++ b/drivers/staging/iio/dac/ad5380.c @@ -389,7 +389,7 @@ static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap, unsigned int ctrl = 0; int ret; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { dev_err(dev, "Failed to allocate iio device\n"); ret = -ENOMEM; @@ -455,7 +455,7 @@ error_free_reg: kfree(indio_dev->channels); error_free: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_regmap_exit: regmap_exit(regmap); @@ -477,7 +477,7 @@ static int __devexit ad5380_remove(struct device *dev) } regmap_exit(st->regmap); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/staging/iio/dac/ad5421.c index b1a893ce2c88..ffbd4c234f57 100644 --- a/drivers/staging/iio/dac/ad5421.c +++ b/drivers/staging/iio/dac/ad5421.c @@ -457,7 +457,7 @@ static int __devinit ad5421_probe(struct spi_device *spi) struct ad5421_state *st; int ret; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { dev_err(&spi->dev, "Failed to allocate iio device\n"); return -ENOMEM; @@ -512,7 +512,7 @@ error_free_irq: if (spi->irq) free_irq(spi->irq, indio_dev); error_free: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -524,7 +524,7 @@ static int __devexit ad5421_remove(struct spi_device *spi) iio_device_unregister(indio_dev); if (spi->irq) free_irq(spi->irq, indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index 62ad1d5df475..3b2551f67a0d 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -296,7 +296,7 @@ static int __devinit ad5446_probe(struct spi_device *spi) voltage_uv = regulator_get_voltage(reg); } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_disable_reg; @@ -331,7 +331,7 @@ static int __devinit ad5446_probe(struct spi_device *spi) return 0; error_free_device: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_disable_reg: if (!IS_ERR(reg)) regulator_disable(reg); @@ -352,7 +352,7 @@ static int ad5446_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 18fc391e62d4..e47f4d0967b4 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -288,7 +288,7 @@ static int __devinit ad5504_probe(struct spi_device *spi) struct regulator *reg; int ret, voltage_uv = 0; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -351,7 +351,7 @@ error_put_reg: if (!IS_ERR(reg)) regulator_put(reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -369,7 +369,7 @@ static int __devexit ad5504_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c index c7786c18b847..cde4a9f8d897 100644 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ b/drivers/staging/iio/dac/ad5624r_spi.c @@ -256,7 +256,7 @@ static int __devinit ad5624r_probe(struct spi_device *spi) struct iio_dev *indio_dev; int ret, voltage_uv = 0; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -306,7 +306,7 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -322,7 +322,7 @@ static int __devexit ad5624r_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c index 86c869134bd4..6a74436af594 100644 --- a/drivers/staging/iio/dac/ad5686.c +++ b/drivers/staging/iio/dac/ad5686.c @@ -359,7 +359,7 @@ static int __devinit ad5686_probe(struct spi_device *spi) struct iio_dev *indio_dev; int ret, regdone = 0, voltage_uv = 0; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -411,7 +411,7 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -426,7 +426,7 @@ static int __devexit ad5686_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5764.c b/drivers/staging/iio/dac/ad5764.c index b01d7eedb95e..03dbd937b081 100644 --- a/drivers/staging/iio/dac/ad5764.c +++ b/drivers/staging/iio/dac/ad5764.c @@ -281,7 +281,7 @@ static int __devinit ad5764_probe(struct spi_device *spi) struct ad5764_state *st; int ret; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { dev_err(&spi->dev, "Failed to allocate iio device\n"); return -ENOMEM; @@ -336,7 +336,7 @@ error_free_reg: if (st->chip_info->int_vref == 0) regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg); error_free: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -353,7 +353,7 @@ static int __devexit ad5764_remove(struct spi_device *spi) regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index c013868dfcd5..1cc75e6cd901 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -289,7 +289,7 @@ static int __devinit ad5791_probe(struct spi_device *spi) struct ad5791_state *st; int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -369,7 +369,7 @@ error_put_reg_neg: error_put_reg_pos: if (!IS_ERR(st->reg_vdd)) regulator_put(st->reg_vdd); - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -390,7 +390,7 @@ static int __devexit ad5791_remove(struct spi_device *spi) regulator_disable(st->reg_vss); regulator_put(st->reg_vss); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c index 373127cc83a8..a3f588dfdbfb 100644 --- a/drivers/staging/iio/dac/max517.c +++ b/drivers/staging/iio/dac/max517.c @@ -218,7 +218,7 @@ static int max517_probe(struct i2c_client *client, struct max517_platform_data *platform_data = client->dev.platform_data; int err; - indio_dev = iio_allocate_device(sizeof(*data)); + indio_dev = iio_device_alloc(sizeof(*data)); if (indio_dev == NULL) { err = -ENOMEM; goto exit; @@ -257,14 +257,14 @@ static int max517_probe(struct i2c_client *client, return 0; exit_free_device: - iio_free_device(indio_dev); + iio_device_free(indio_dev); exit: return err; } static int max517_remove(struct i2c_client *client) { - iio_free_device(i2c_get_clientdata(client)); + iio_device_free(i2c_get_clientdata(client)); return 0; } diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c index 6df4d86be849..97542fc9bf22 100644 --- a/drivers/staging/iio/dds/ad5930.c +++ b/drivers/staging/iio/dds/ad5930.c @@ -97,7 +97,7 @@ static int __devinit ad5930_probe(struct spi_device *spi) struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); + idev = iio_device_alloc(sizeof(*st)); if (idev == NULL) { ret = -ENOMEM; goto error_ret; @@ -122,7 +122,7 @@ static int __devinit ad5930_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(idev); + iio_device_free(idev); error_ret: return ret; } @@ -130,7 +130,7 @@ error_ret: static int __devexit ad5930_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c index 57627ff45c3a..7a9b723d51e0 100644 --- a/drivers/staging/iio/dds/ad9832.c +++ b/drivers/staging/iio/dds/ad9832.c @@ -221,7 +221,7 @@ static int __devinit ad9832_probe(struct spi_device *spi) goto error_put_reg; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_disable_reg; @@ -313,7 +313,7 @@ static int __devinit ad9832_probe(struct spi_device *spi) return 0; error_free_device: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_disable_reg: if (!IS_ERR(reg)) regulator_disable(reg); @@ -334,7 +334,7 @@ static int __devexit ad9832_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c index 9b2c8795f894..b8ef8d9be550 100644 --- a/drivers/staging/iio/dds/ad9834.c +++ b/drivers/staging/iio/dds/ad9834.c @@ -334,7 +334,7 @@ static int __devinit ad9834_probe(struct spi_device *spi) goto error_put_reg; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_disable_reg; @@ -414,7 +414,7 @@ static int __devinit ad9834_probe(struct spi_device *spi) return 0; error_free_device: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_disable_reg: if (!IS_ERR(reg)) regulator_disable(reg); @@ -434,7 +434,7 @@ static int __devexit ad9834_remove(struct spi_device *spi) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c index cc7a87d25a59..39f12a6a08b4 100644 --- a/drivers/staging/iio/dds/ad9850.c +++ b/drivers/staging/iio/dds/ad9850.c @@ -83,7 +83,7 @@ static int __devinit ad9850_probe(struct spi_device *spi) struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); + idev = iio_device_alloc(sizeof(*st)); if (idev == NULL) { ret = -ENOMEM; goto error_ret; @@ -108,7 +108,7 @@ static int __devinit ad9850_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(idev); + iio_device_free(idev); error_ret: return ret; } @@ -116,7 +116,7 @@ error_ret: static int __devexit ad9850_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c index 2f8df7bcb783..58d4bf89e64e 100644 --- a/drivers/staging/iio/dds/ad9852.c +++ b/drivers/staging/iio/dds/ad9852.c @@ -232,7 +232,7 @@ static int __devinit ad9852_probe(struct spi_device *spi) struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); + idev = iio_device_alloc(sizeof(*st)); if (idev == NULL) { ret = -ENOMEM; goto error_ret; @@ -258,7 +258,7 @@ static int __devinit ad9852_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(idev); + iio_device_free(idev); error_ret: return ret; @@ -267,7 +267,7 @@ error_ret: static int __devexit ad9852_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c index e91efc5c0fca..6e7a97e92a20 100644 --- a/drivers/staging/iio/dds/ad9910.c +++ b/drivers/staging/iio/dds/ad9910.c @@ -367,7 +367,7 @@ static int __devinit ad9910_probe(struct spi_device *spi) struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); + idev = iio_device_alloc(sizeof(*st)); if (idev == NULL) { ret = -ENOMEM; goto error_ret; @@ -392,7 +392,7 @@ static int __devinit ad9910_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(idev); + iio_device_free(idev); error_ret: return ret; } @@ -400,7 +400,7 @@ error_ret: static int __devexit ad9910_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c index ca1d3111b0bf..19ba721788fe 100644 --- a/drivers/staging/iio/dds/ad9951.c +++ b/drivers/staging/iio/dds/ad9951.c @@ -176,7 +176,7 @@ static int __devinit ad9951_probe(struct spi_device *spi) struct iio_dev *idev; int ret = 0; - idev = iio_allocate_device(sizeof(*st)); + idev = iio_device_alloc(sizeof(*st)); if (idev == NULL) { ret = -ENOMEM; goto error_ret; @@ -202,7 +202,7 @@ static int __devinit ad9951_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(idev); + iio_device_free(idev); error_ret: return ret; @@ -211,7 +211,7 @@ error_ret: static int __devexit ad9951_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c index 08aaf2783895..9931e2060e1f 100644 --- a/drivers/staging/iio/gyro/adis16060_core.c +++ b/drivers/staging/iio/gyro/adis16060_core.c @@ -152,7 +152,7 @@ static int __devinit adis16060_r_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -178,7 +178,7 @@ static int __devinit adis16060_r_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -187,7 +187,7 @@ error_ret: static int adis16060_r_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index 7e3695ba628b..11f1dccd7a0d 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c @@ -145,7 +145,7 @@ static int __devinit adis16080_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -171,7 +171,7 @@ static int __devinit adis16080_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -180,7 +180,7 @@ error_ret: static int adis16080_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c index 98aa1b92b9d4..bf61cd0b5bbc 100644 --- a/drivers/staging/iio/gyro/adis16130_core.c +++ b/drivers/staging/iio/gyro/adis16130_core.c @@ -123,7 +123,7 @@ static int __devinit adis16130_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -147,7 +147,7 @@ static int __devinit adis16130_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -157,7 +157,7 @@ error_ret: static int adis16130_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 15253beab9a0..d7979cf15cd0 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -627,7 +627,7 @@ static int __devinit adis16260_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -712,7 +712,7 @@ error_uninitialize_ring: error_unreg_ring_funcs: adis16260_unconfigure_ring(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -733,7 +733,7 @@ static int adis16260_remove(struct spi_device *spi) adis16260_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16260_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); err_ret: return ret; diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c index dc56f3263762..034559e4d5b9 100644 --- a/drivers/staging/iio/gyro/adis16260_trigger.c +++ b/drivers/staging/iio/gyro/adis16260_trigger.c @@ -29,7 +29,7 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev) int ret; struct adis16260_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("%s-dev%d", + st->trig = iio_trigger_alloc("%s-dev%d", spi_get_device_id(st->us)->name, indio_dev->id); if (st->trig == NULL) { @@ -60,7 +60,7 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -71,5 +71,5 @@ void adis16260_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 06a9e974f010..6513119b1e90 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -372,7 +372,7 @@ static int __devinit adxrs450_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -403,7 +403,7 @@ static int __devinit adxrs450_probe(struct spi_device *spi) error_initial: iio_device_unregister(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -412,7 +412,7 @@ error_ret: static int adxrs450_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index fa4a65329009..3b4513cf5ab9 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -392,7 +392,7 @@ static int __devinit iio_dummy_probe(int index) * It also has a region (accessed by iio_priv() * for chip specific state information. */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -472,7 +472,7 @@ error_unregister_events: error_free_device: /* Note free device should only be called, before registration * has succeeded. */ - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -509,7 +509,7 @@ static int iio_dummy_remove(int index) goto error_ret; /* Free all structures */ - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 9d99a7f67fa4..359a794f684a 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -705,7 +705,7 @@ static int __devinit ad5933_probe(struct i2c_client *client, int ret, voltage_uv = 0; struct ad5933_platform_data *pdata = client->dev.platform_data; struct ad5933_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -784,7 +784,7 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -801,7 +801,7 @@ static __devexit int ad5933_remove(struct i2c_client *client) regulator_disable(st->reg); regulator_put(st->reg); } - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 68ecc1525017..5015f823b65f 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -1161,7 +1161,7 @@ static int __devinit adis16400_probe(struct spi_device *spi) { int ret; struct adis16400_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -1218,7 +1218,7 @@ error_uninitialize_ring: error_unreg_ring_funcs: adis16400_unconfigure_ring(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -1237,7 +1237,7 @@ static int adis16400_remove(struct spi_device *spi) adis16400_remove_trigger(indio_dev); iio_buffer_unregister(indio_dev); adis16400_unconfigure_ring(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; diff --git a/drivers/staging/iio/imu/adis16400_trigger.c b/drivers/staging/iio/imu/adis16400_trigger.c index bd22e6cc11c3..42a678e92fc6 100644 --- a/drivers/staging/iio/imu/adis16400_trigger.c +++ b/drivers/staging/iio/imu/adis16400_trigger.c @@ -29,7 +29,7 @@ int adis16400_probe_trigger(struct iio_dev *indio_dev) int ret; struct adis16400_state *st = iio_priv(indio_dev); - st->trig = iio_allocate_trigger("%s-dev%d", + st->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id); if (st->trig == NULL) { @@ -59,7 +59,7 @@ int adis16400_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -70,5 +70,5 @@ void adis16400_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 92283ebafa55..2d23c6afa286 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -532,7 +532,7 @@ static int __devinit isl29018_probe(struct i2c_client *client, struct iio_dev *indio_dev; int err; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { dev_err(&client->dev, "iio allocation fails\n"); err = -ENOMEM; @@ -574,7 +574,7 @@ static int __devinit isl29018_probe(struct i2c_client *client, return 0; exit_iio_free: - iio_free_device(indio_dev); + iio_device_free(indio_dev); exit: return err; } @@ -585,7 +585,7 @@ static int __devexit isl29018_remove(struct i2c_client *client) dev_dbg(&client->dev, "%s()\n", __func__); iio_device_unregister(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 2ada20e65f22..33a4c3f94a14 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -482,7 +482,7 @@ static int __devinit isl29028_probe(struct i2c_client *client, struct iio_dev *indio_dev; int ret; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (!indio_dev) { dev_err(&client->dev, "iio allocation fails\n"); return -ENOMEM; @@ -522,7 +522,7 @@ static int __devinit isl29028_probe(struct i2c_client *client, return 0; exit_iio_free: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -531,7 +531,7 @@ static int __devexit isl29028_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 635136004103..9d740be43a82 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -714,7 +714,7 @@ static int __devinit tsl2563_probe(struct i2c_client *client, int err = 0; u8 id = 0; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (!indio_dev) return -ENOMEM; @@ -801,7 +801,7 @@ fail2: if (client->irq) free_irq(client->irq, indio_dev); fail1: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return err; } @@ -822,7 +822,7 @@ static int tsl2563_remove(struct i2c_client *client) if (client->irq) free_irq(client->irq, indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 51b636241d97..5ff391e8c18b 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -815,7 +815,7 @@ static int __devinit taos_probe(struct i2c_client *clientp, return -EOPNOTSUPP; } - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (indio_dev == NULL) { ret = -ENOMEM; dev_err(&clientp->dev, "iio allocation failed\n"); @@ -879,7 +879,7 @@ static int __devinit taos_probe(struct i2c_client *clientp, dev_info(&clientp->dev, "Light sensor found.\n"); return 0; fail1: - iio_free_device(indio_dev); + iio_device_free(indio_dev); fail2: return ret; } @@ -926,7 +926,7 @@ static SIMPLE_DEV_PM_OPS(taos_pm_ops, taos_suspend, taos_resume); static int __devexit taos_remove(struct i2c_client *client) { iio_device_unregister(i2c_get_clientdata(client)); - iio_free_device(i2c_get_clientdata(client)); + iio_device_free(i2c_get_clientdata(client)); return 0; } diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index dfc3da6e92e9..efbc4d27e794 100755 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -1906,7 +1906,7 @@ static int __devinit tsl2x7x_probe(struct i2c_client *clientp, struct iio_dev *indio_dev; struct tsl2X7X_chip *chip; - indio_dev = iio_allocate_device(sizeof(*chip)); + indio_dev = iio_device_alloc(sizeof(*chip)); if (!indio_dev) return -ENOMEM; @@ -1986,7 +1986,7 @@ fail1: if (clientp->irq) free_irq(clientp->irq, indio_dev); fail2: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -2038,7 +2038,7 @@ static int __devexit tsl2x7x_remove(struct i2c_client *client) if (client->irq) free_irq(client->irq, chip->client->name); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index d088548c2fa8..ea2f91859ce4 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -504,7 +504,7 @@ static int ak8975_probe(struct i2c_client *client, } /* Register with IIO */ - indio_dev = iio_allocate_device(sizeof(*data)); + indio_dev = iio_device_alloc(sizeof(*data)); if (indio_dev == NULL) { err = -ENOMEM; goto exit_gpio; @@ -535,7 +535,7 @@ static int ak8975_probe(struct i2c_client *client, return 0; exit_free_iio: - iio_free_device(indio_dev); + iio_device_free(indio_dev); exit_gpio: if (gpio_is_valid(eoc_gpio)) gpio_free(eoc_gpio); @@ -553,7 +553,7 @@ static int ak8975_remove(struct i2c_client *client) if (gpio_is_valid(data->eoc_gpio)) gpio_free(data->eoc_gpio); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 3433c41fe548..e7cc9e04998e 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -544,7 +544,7 @@ static int hmc5843_probe(struct i2c_client *client, struct iio_dev *indio_dev; int err = 0; - indio_dev = iio_allocate_device(sizeof(*data)); + indio_dev = iio_device_alloc(sizeof(*data)); if (indio_dev == NULL) { err = -ENOMEM; goto exit; @@ -572,7 +572,7 @@ static int hmc5843_probe(struct i2c_client *client, goto exit_free2; return 0; exit_free2: - iio_free_device(indio_dev); + iio_device_free(indio_dev); exit: return err; } @@ -584,7 +584,7 @@ static int hmc5843_remove(struct i2c_client *client) iio_device_unregister(indio_dev); /* sleep mode to save power */ hmc5843_configure(client, MODE_SLEEP); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 9b26ae1f23b7..280331b664f4 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -517,7 +517,7 @@ static int __devinit ade7753_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -546,7 +546,7 @@ static int __devinit ade7753_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -564,7 +564,7 @@ static int ade7753_remove(struct spi_device *spi) if (ret) goto err_ret; - iio_free_device(indio_dev); + iio_device_free(indio_dev); err_ret: return ret; } diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index 02d10dfe8ac5..59a2e3ef72b5 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -540,7 +540,7 @@ static int __devinit ade7754_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -568,7 +568,7 @@ static int __devinit ade7754_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; @@ -585,7 +585,7 @@ static int ade7754_remove(struct spi_device *spi) if (ret) goto err_ret; - iio_free_device(indio_dev); + iio_device_free(indio_dev); err_ret: return ret; diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 4a3b429003f1..1a5c9c408141 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -885,7 +885,7 @@ static int __devinit ade7758_probe(struct spi_device *spi) { int i, ret; struct ade7758_state *st; - struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); + struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; @@ -962,7 +962,7 @@ error_free_tx: error_free_rx: kfree(st->rx); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -984,7 +984,7 @@ static int ade7758_remove(struct spi_device *spi) kfree(st->tx); kfree(st->rx); - iio_free_device(indio_dev); + iio_device_free(indio_dev); err_ret: return ret; diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c index 5c48d382dfdb..f9c6a340092b 100644 --- a/drivers/staging/iio/meter/ade7758_trigger.c +++ b/drivers/staging/iio/meter/ade7758_trigger.c @@ -63,7 +63,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) struct ade7758_state *st = iio_priv(indio_dev); int ret; - st->trig = iio_allocate_trigger("%s-dev%d", + st->trig = iio_trigger_alloc("%s-dev%d", spi_get_device_id(st->us)->name, indio_dev->id); if (st->trig == NULL) { @@ -94,7 +94,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->us->irq, st->trig); error_free_trig: - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); error_ret: return ret; } @@ -105,5 +105,5 @@ void ade7758_remove_trigger(struct iio_dev *indio_dev) iio_trigger_unregister(st->trig); free_irq(st->us->irq, st->trig); - iio_free_trigger(st->trig); + iio_trigger_free(st->trig); } diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 1f2b74add572..91add54af111 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -463,7 +463,7 @@ static int __devinit ade7759_probe(struct spi_device *spi) struct iio_dev *indio_dev; /* setup the industrialio driver allocated elements */ - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -491,7 +491,7 @@ static int __devinit ade7759_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -507,7 +507,7 @@ static int ade7759_remove(struct spi_device *spi) if (ret) goto err_ret; - iio_free_device(indio_dev); + iio_device_free(indio_dev); err_ret: return ret; diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c index c87c86b095e0..527aa97c74ae 100644 --- a/drivers/staging/iio/meter/ade7854-i2c.c +++ b/drivers/staging/iio/meter/ade7854-i2c.c @@ -208,7 +208,7 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client, struct ade7854_state *st; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); @@ -226,7 +226,7 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client, ret = ade7854_probe(indio_dev, &client->dev); if (ret) - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c index 11c2cef0e73b..eaafaef9caec 100644 --- a/drivers/staging/iio/meter/ade7854-spi.c +++ b/drivers/staging/iio/meter/ade7854-spi.c @@ -306,7 +306,7 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi) struct ade7854_state *st; struct iio_dev *indio_dev; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); @@ -325,7 +325,7 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi) ret = ade7854_probe(indio_dev, &spi->dev); if (ret) - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index 2f3c1e2a4b14..fa3ba01af41d 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -581,7 +581,7 @@ int ade7854_probe(struct iio_dev *indio_dev, struct device *dev) error_unreg_dev: iio_device_unregister(indio_dev); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); return ret; } @@ -590,7 +590,7 @@ EXPORT_SYMBOL(ade7854_probe); int ade7854_remove(struct iio_dev *indio_dev) { iio_device_unregister(indio_dev); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index 48e70e9effd5..8b71eb0e16f5 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -112,7 +112,7 @@ static int __devinit ad2s1200_probe(struct spi_device *spi) DRV_NAME, pins[pn]); goto error_ret; } - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -142,7 +142,7 @@ static int __devinit ad2s1200_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: for (--pn; pn >= 0; pn--) gpio_free(pins[pn]); @@ -152,7 +152,7 @@ error_ret: static int __devexit ad2s1200_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index 4d580e238eb8..a236ddbee372 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -690,7 +690,7 @@ static int __devinit ad2s1210_probe(struct spi_device *spi) if (spi->dev.platform_data == NULL) return -EINVAL; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -731,7 +731,7 @@ static int __devinit ad2s1210_probe(struct spi_device *spi) error_free_gpios: ad2s1210_free_gpios(st); error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -742,7 +742,7 @@ static int __devexit ad2s1210_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ad2s1210_free_gpios(iio_priv(indio_dev)); - iio_free_device(indio_dev); + iio_device_free(indio_dev); return 0; } diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c index cb689104937f..a8057228dca1 100644 --- a/drivers/staging/iio/resolver/ad2s90.c +++ b/drivers/staging/iio/resolver/ad2s90.c @@ -64,7 +64,7 @@ static int __devinit ad2s90_probe(struct spi_device *spi) struct ad2s90_state *st; int ret = 0; - indio_dev = iio_allocate_device(sizeof(*st)); + indio_dev = iio_device_alloc(sizeof(*st)); if (indio_dev == NULL) { ret = -ENOMEM; goto error_ret; @@ -93,7 +93,7 @@ static int __devinit ad2s90_probe(struct spi_device *spi) return 0; error_free_dev: - iio_free_device(indio_dev); + iio_device_free(indio_dev); error_ret: return ret; } @@ -101,7 +101,7 @@ error_ret: static int __devexit ad2s90_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_free_device(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 999fd2e00e81..f85734d212bb 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -172,7 +172,7 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) st->timer_num = ret; st->t = &iio_bfin_timer_code[st->timer_num]; - st->trig = iio_allocate_trigger("bfintmr%d", st->timer_num); + st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num); if (!st->trig) { ret = -ENOMEM; goto out1; @@ -203,7 +203,7 @@ static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev) out4: iio_trigger_unregister(st->trig); out2: - iio_put_trigger(st->trig); + iio_trigger_put(st->trig); out1: kfree(st); out: @@ -217,7 +217,7 @@ static int __devexit iio_bfin_tmr_trigger_remove(struct platform_device *pdev) disable_gptimers(st->t->bit); free_irq(st->irq, st); iio_trigger_unregister(st->trig); - iio_put_trigger(st->trig); + iio_trigger_put(st->trig); kfree(st); return 0; diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c index 95fd2f780f52..90b26846fc6b 100644 --- a/drivers/staging/iio/trigger/iio-trig-gpio.c +++ b/drivers/staging/iio/trigger/iio-trig-gpio.c @@ -72,7 +72,7 @@ static int iio_gpio_trigger_probe(struct platform_device *pdev) for (irq = irq_res->start; irq <= irq_res->end; irq++) { - trig = iio_allocate_trigger("irqtrig%d", irq); + trig = iio_trigger_alloc("irqtrig%d", irq); if (!trig) { ret = -ENOMEM; goto error_free_completed_registrations; @@ -114,7 +114,7 @@ error_release_irq: error_free_trig_info: kfree(trig_info); error_put_trigger: - iio_put_trigger(trig); + iio_trigger_put(trig); error_free_completed_registrations: /* The rest should have been added to the iio_gpio_trigger_list */ list_for_each_entry_safe(trig, @@ -144,7 +144,7 @@ static int iio_gpio_trigger_remove(struct platform_device *pdev) iio_trigger_unregister(trig); free_irq(trig_info->irq, trig); kfree(trig_info); - iio_put_trigger(trig); + iio_trigger_put(trig); } mutex_unlock(&iio_gpio_trigger_list_lock); diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c index 2c3ccda745eb..9f2d055524a3 100644 --- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c @@ -112,7 +112,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev) for (i = 0;; i++) { if (pdata[i] == NULL) break; - trig = iio_allocate_trigger("periodic%s", pdata[i]); + trig = iio_trigger_alloc("periodic%s", pdata[i]); if (!trig) { ret = -ENOMEM; goto error_free_completed_registrations; @@ -152,7 +152,7 @@ error_free_trig_info: kfree(trig_info); error_put_trigger_and_remove_from_list: list_del(&trig->alloc_list); - iio_put_trigger(trig); + iio_trigger_put(trig); error_free_completed_registrations: list_for_each_entry_safe(trig, trig2, diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c index 404ef192f89f..552763bb3d4c 100644 --- a/drivers/staging/iio/trigger/iio-trig-sysfs.c +++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c @@ -139,7 +139,7 @@ static int iio_sysfs_trigger_probe(int id) goto out1; } t->id = id; - t->trig = iio_allocate_trigger("sysfstrig%d", id); + t->trig = iio_trigger_alloc("sysfstrig%d", id); if (!t->trig) { ret = -ENOMEM; goto free_t; @@ -158,7 +158,7 @@ static int iio_sysfs_trigger_probe(int id) return 0; out2: - iio_put_trigger(t->trig); + iio_trigger_put(t->trig); free_t: kfree(t); out1: @@ -182,7 +182,7 @@ static int iio_sysfs_trigger_remove(int id) } iio_trigger_unregister(t->trig); - iio_free_trigger(t->trig); + iio_trigger_free(t->trig); list_del(&t->l); kfree(t); diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 9c0908a70466..d21833909327 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -400,10 +400,10 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp); extern struct bus_type iio_bus_type; /** - * iio_put_device() - reference counted deallocation of struct device + * iio_device_put() - reference counted deallocation of struct device * @dev: the iio_device containing the device **/ -static inline void iio_put_device(struct iio_dev *indio_dev) +static inline void iio_device_put(struct iio_dev *indio_dev) { if (indio_dev) put_device(&indio_dev->dev); @@ -412,10 +412,10 @@ static inline void iio_put_device(struct iio_dev *indio_dev) /* Can we make this smaller? */ #define IIO_ALIGN L1_CACHE_BYTES /** - * iio_allocate_device() - allocate an iio_dev from a driver + * iio_device_alloc() - allocate an iio_dev from a driver * @sizeof_priv: Space to allocate for private structure. **/ -struct iio_dev *iio_allocate_device(int sizeof_priv); +struct iio_dev *iio_device_alloc(int sizeof_priv); static inline void *iio_priv(const struct iio_dev *indio_dev) { @@ -429,10 +429,10 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) } /** - * iio_free_device() - free an iio_dev from a driver + * iio_device_free() - free an iio_dev from a driver * @dev: the iio_dev associated with the device **/ -void iio_free_device(struct iio_dev *indio_dev); +void iio_device_free(struct iio_dev *indio_dev); /** * iio_buffer_enabled() - helper function to test if the buffer is enabled diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index 1cfca231db8f..a9819940a84c 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -78,13 +78,13 @@ static inline struct iio_trigger *to_iio_trigger(struct device *d) return container_of(d, struct iio_trigger, dev); }; -static inline void iio_put_trigger(struct iio_trigger *trig) +static inline void iio_trigger_put(struct iio_trigger *trig) { module_put(trig->ops->owner); put_device(&trig->dev); }; -static inline void iio_get_trigger(struct iio_trigger *trig) +static inline void iio_trigger_get(struct iio_trigger *trig) { get_device(&trig->dev); __module_get(trig->ops->owner); @@ -113,7 +113,7 @@ void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time); irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); -__printf(1, 2) struct iio_trigger *iio_allocate_trigger(const char *fmt, ...); -void iio_free_trigger(struct iio_trigger *trig); +__printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...); +void iio_trigger_free(struct iio_trigger *trig); #endif /* _IIO_TRIGGER_H_ */ -- cgit v1.2.3-71-gd317 From a6b12855b58bff429f3961e2577b8bbbb48fe470 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 27 Apr 2012 10:58:34 +0200 Subject: iio: core: Introduce IIO_ALTVOLTAGE and appropriate channel info elements Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/industrialio-core.c | 3 +++ include/linux/iio/iio.h | 10 ++++++++++ include/linux/iio/types.h | 1 + 3 files changed, 14 insertions(+) (limited to 'include/linux') diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index e8e280d64295..47a72473d0b5 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -63,6 +63,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_ANGL] = "angl", [IIO_TIMESTAMP] = "timestamp", [IIO_CAPACITANCE] = "capacitance", + [IIO_ALTVOLTAGE] = "altvoltage", }; static const char * const iio_modifier_names[] = { @@ -88,6 +89,8 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] = "filter_low_pass_3db_frequency", [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency", + [IIO_CHAN_INFO_FREQUENCY] = "frequency", + [IIO_CHAN_INFO_PHASE] = "phase", }; const struct iio_chan_spec diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index d21833909327..43002b2b1e38 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -32,6 +32,8 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_AVERAGE_RAW, IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY, IIO_CHAN_INFO_SAMP_FREQ, + IIO_CHAN_INFO_FREQUENCY, + IIO_CHAN_INFO_PHASE, }; #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) @@ -85,6 +87,14 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SAMP_FREQ) #define IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT \ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SAMP_FREQ) +#define IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_FREQUENCY) +#define IIO_CHAN_INFO_FREQUENCY_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_FREQUENCY) +#define IIO_CHAN_INFO_PHASE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PHASE) +#define IIO_CHAN_INFO_PHASE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PHASE) enum iio_endian { IIO_CPU, diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 0c3213666901..a471fd5a4d95 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -27,6 +27,7 @@ enum iio_chan_type { IIO_ANGL, IIO_TIMESTAMP, IIO_CAPACITANCE, + IIO_ALTVOLTAGE, }; enum iio_modifier { -- cgit v1.2.3-71-gd317 From fc6d11398e22a3b2cfd7c3b8421653c6075b624b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 27 Apr 2012 10:58:36 +0200 Subject: iio: core: iio_chan_spec_ext_info: Add private handle There is currently no user, but we might need it in future. So better add it now, before we have to convert drivers afterwards. Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/industrialio-core.c | 5 +++-- drivers/staging/iio/dac/ad5064.c | 12 +++++++----- drivers/staging/iio/dac/ad5446.c | 6 +++++- include/linux/iio/iio.h | 11 +++++++---- 4 files changed, 22 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 47a72473d0b5..72e33b819f91 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -281,7 +281,7 @@ static ssize_t iio_read_channel_ext_info(struct device *dev, ext_info = &this_attr->c->ext_info[this_attr->address]; - return ext_info->read(indio_dev, this_attr->c, buf); + return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf); } static ssize_t iio_write_channel_ext_info(struct device *dev, @@ -295,7 +295,8 @@ static ssize_t iio_write_channel_ext_info(struct device *dev, ext_info = &this_attr->c->ext_info[this_attr->address]; - return ext_info->write(indio_dev, this_attr->c, buf, len); + return ext_info->write(indio_dev, ext_info->private, + this_attr->c, buf, len); } static ssize_t iio_read_channel_info(struct device *dev, diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index bce641a1cf82..047148aa66b2 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -144,14 +144,14 @@ static const char ad5064_powerdown_modes[][15] = { }; static ssize_t ad5064_read_powerdown_mode_available(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, char *buf) + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { return sprintf(buf, "%s %s %s\n", ad5064_powerdown_modes[1], ad5064_powerdown_modes[2], ad5064_powerdown_modes[3]); } static ssize_t ad5064_read_powerdown_mode(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, char *buf) + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { struct ad5064_state *st = iio_priv(indio_dev); @@ -160,7 +160,8 @@ static ssize_t ad5064_read_powerdown_mode(struct iio_dev *indio_dev, } static ssize_t ad5064_write_powerdown_mode(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, const char *buf, size_t len) + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) { struct ad5064_state *st = iio_priv(indio_dev); unsigned int mode, i; @@ -187,7 +188,7 @@ static ssize_t ad5064_write_powerdown_mode(struct iio_dev *indio_dev, } static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, char *buf) + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { struct ad5064_state *st = iio_priv(indio_dev); @@ -195,7 +196,8 @@ static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, } static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, const char *buf, size_t len) + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) { struct ad5064_state *st = iio_priv(indio_dev); bool pwr_down; diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index 3b2551f67a0d..daa65b384c13 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -46,13 +46,14 @@ static const char * const ad5446_powerdown_modes[] = { }; static ssize_t ad5446_read_powerdown_mode_available(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, char *buf) + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { return sprintf(buf, "%s %s %s\n", ad5446_powerdown_modes[1], ad5446_powerdown_modes[2], ad5446_powerdown_modes[3]); } static ssize_t ad5446_write_powerdown_mode(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, size_t len) { @@ -73,6 +74,7 @@ static ssize_t ad5446_write_powerdown_mode(struct iio_dev *indio_dev, } static ssize_t ad5446_read_powerdown_mode(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { @@ -82,6 +84,7 @@ static ssize_t ad5446_read_powerdown_mode(struct iio_dev *indio_dev, } static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) { @@ -91,6 +94,7 @@ static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev, } static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, size_t len) { diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 43002b2b1e38..6fdbdb858e35 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -111,14 +111,17 @@ struct iio_dev; * @shared: Whether this attribute is shared between all channels. * @read: Read callback for this info attribute, may be NULL. * @write: Write callback for this info attribute, may be NULL. + * @private: Data private to the driver. */ struct iio_chan_spec_ext_info { const char *name; bool shared; - ssize_t (*read)(struct iio_dev *, struct iio_chan_spec const *, - char *buf); - ssize_t (*write)(struct iio_dev *, struct iio_chan_spec const *, - const char *buf, size_t len); + ssize_t (*read)(struct iio_dev *, uintptr_t private, + struct iio_chan_spec const *, char *buf); + ssize_t (*write)(struct iio_dev *, uintptr_t private, + struct iio_chan_spec const *, const char *buf, + size_t len); + uintptr_t private; }; /** -- cgit v1.2.3-71-gd317 From b544f3fd3ac509850f8f1c28b302ae4e65b88346 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 May 2012 16:38:58 +0300 Subject: uuid: add uuid.h to exported header list uuid is used in mei.h interface Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- include/linux/Kbuild | 1 + include/linux/uuid.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 3c9b616c834a..137dd4bb4ba7 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -381,6 +381,7 @@ header-y += unistd.h header-y += usbdevice_fs.h header-y += utime.h header-y += utsname.h +header-y += uuid.h header-y += uvcvideo.h header-y += v4l2-mediabus.h header-y += v4l2-subdev.h diff --git a/include/linux/uuid.h b/include/linux/uuid.h index 5b7efbfcee4e..f86c37bfd4a0 100644 --- a/include/linux/uuid.h +++ b/include/linux/uuid.h @@ -54,6 +54,8 @@ typedef struct { UUID_BE(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00) +#ifdef __KERNEL__ + static inline int uuid_le_cmp(const uuid_le u1, const uuid_le u2) { return memcmp(&u1, &u2, sizeof(uuid_le)); @@ -67,4 +69,6 @@ static inline int uuid_be_cmp(const uuid_be u1, const uuid_be u2) extern void uuid_le_gen(uuid_le *u); extern void uuid_be_gen(uuid_be *u); +#endif /* __KERNEL__ */ + #endif -- cgit v1.2.3-71-gd317 From 4f3afe1d8c8e5dc41bb5820c01b4f3cfc2dc1205 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 May 2012 16:38:59 +0300 Subject: mei: export mei.h for the user space The header exports API for application layer 1. move under include/linux and add to the export list 2. update include path n the sources 3. update TODO Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/TODO | 1 - drivers/misc/mei/init.c | 2 +- drivers/misc/mei/interface.c | 2 +- drivers/misc/mei/interface.h | 2 +- drivers/misc/mei/interrupt.c | 2 +- drivers/misc/mei/iorw.c | 2 +- drivers/misc/mei/main.c | 2 +- drivers/misc/mei/mei-amt-version.c | 2 +- drivers/misc/mei/mei.h | 110 ------------------------------------- drivers/misc/mei/mei_dev.h | 2 +- drivers/misc/mei/wd.c | 2 +- include/linux/Kbuild | 1 + include/linux/mei.h | 110 +++++++++++++++++++++++++++++++++++++ 13 files changed, 120 insertions(+), 120 deletions(-) delete mode 100644 drivers/misc/mei/mei.h create mode 100644 include/linux/mei.h (limited to 'include/linux') diff --git a/drivers/misc/mei/TODO b/drivers/misc/mei/TODO index fc266018355e..ed4d16c30ab5 100644 --- a/drivers/misc/mei/TODO +++ b/drivers/misc/mei/TODO @@ -1,7 +1,6 @@ TODO: - Cleanup and split the timer function Upon Unstaging: - - move mei.h to include/linux/mei.h - Documentation/ioctl/ioctl-number.txt - move mei.txt under Documentation/mei/ - move mei-amt-version.c under Documentation/mei diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index afb0a583b566..a7d0bb0880ec 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -22,7 +22,7 @@ #include "mei_dev.h" #include "hw.h" #include "interface.h" -#include "mei.h" +#include const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c index 9a2cfafc52a6..428d21e36416 100644 --- a/drivers/misc/mei/interface.c +++ b/drivers/misc/mei/interface.c @@ -16,7 +16,7 @@ #include #include "mei_dev.h" -#include "mei.h" +#include #include "interface.h" diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h index 0d0043575a2a..ddff5d16616f 100644 --- a/drivers/misc/mei/interface.h +++ b/drivers/misc/mei/interface.h @@ -19,7 +19,7 @@ #ifndef _MEI_INTERFACE_H_ #define _MEI_INTERFACE_H_ -#include "mei.h" +#include #include "mei_dev.h" diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 2007d2447b1c..93936f1b75eb 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -22,7 +22,7 @@ #include #include "mei_dev.h" -#include "mei.h" +#include #include "hw.h" #include "interface.h" diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c index 0a80dc4e62f3..f9cced69b65e 100644 --- a/drivers/misc/mei/iorw.c +++ b/drivers/misc/mei/iorw.c @@ -35,7 +35,7 @@ #include "mei_dev.h" #include "hw.h" -#include "mei.h" +#include #include "interface.h" diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 6510c5adac2a..c70333228337 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -38,7 +38,7 @@ #include #include "mei_dev.h" -#include "mei.h" +#include #include "interface.h" static const char mei_driver_name[] = "mei"; diff --git a/drivers/misc/mei/mei-amt-version.c b/drivers/misc/mei/mei-amt-version.c index ac2a507be253..01804f216312 100644 --- a/drivers/misc/mei/mei-amt-version.c +++ b/drivers/misc/mei/mei-amt-version.c @@ -74,7 +74,7 @@ #include #include #include -#include "mei.h" +#include /***************************************************************************** * Intel Management Engine Interface diff --git a/drivers/misc/mei/mei.h b/drivers/misc/mei/mei.h deleted file mode 100644 index bc0d8b69c49e..000000000000 --- a/drivers/misc/mei/mei.h +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** - * Intel Management Engine Interface (Intel MEI) Linux driver - * Intel MEI Interface Header - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Corporation. - * linux-mei@linux.intel.com - * http://www.intel.com - * - * BSD LICENSE - * - * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#ifndef _LINUX_MEI_H -#define _LINUX_MEI_H - -#include - -/* - * This IOCTL is used to associate the current file descriptor with a - * FW Client (given by UUID). This opens a communication channel - * between a host client and a FW client. From this point every read and write - * will communicate with the associated FW client. - * Only in close() (file_operation release()) the communication between - * the clients is disconnected - * - * The IOCTL argument is a struct with a union that contains - * the input parameter and the output parameter for this IOCTL. - * - * The input parameter is UUID of the FW Client. - * The output parameter is the properties of the FW client - * (FW protocol version and max message size). - * - */ -#define IOCTL_MEI_CONNECT_CLIENT \ - _IOWR('H' , 0x01, struct mei_connect_client_data) - -/* - * Intel MEI client information struct - */ -struct mei_client { - __u32 max_msg_length; - __u8 protocol_version; - __u8 reserved[3]; -}; - -/* - * IOCTL Connect Client Data structure - */ -struct mei_connect_client_data { - union { - uuid_le in_client_uuid; - struct mei_client out_client_properties; - }; -}; - -#endif /* _LINUX_MEI_H */ diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 10b1b4e2f8ac..63d7ee97c5fb 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -19,7 +19,7 @@ #include #include -#include "mei.h" +#include #include "hw.h" /* diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 1e6285127e95..6be5605707b4 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -24,7 +24,7 @@ #include "mei_dev.h" #include "hw.h" #include "interface.h" -#include "mei.h" +#include static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 137dd4bb4ba7..b344a664c1f1 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -240,6 +240,7 @@ header-y += map_to_7segment.h header-y += matroxfb.h header-y += mdio.h header-y += media.h +header-y += mei.h header-y += mempolicy.h header-y += meye.h header-y += mii.h diff --git a/include/linux/mei.h b/include/linux/mei.h new file mode 100644 index 000000000000..bc0d8b69c49e --- /dev/null +++ b/include/linux/mei.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * Intel Management Engine Interface (Intel MEI) Linux driver + * Intel MEI Interface Header + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Corporation. + * linux-mei@linux.intel.com + * http://www.intel.com + * + * BSD LICENSE + * + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#ifndef _LINUX_MEI_H +#define _LINUX_MEI_H + +#include + +/* + * This IOCTL is used to associate the current file descriptor with a + * FW Client (given by UUID). This opens a communication channel + * between a host client and a FW client. From this point every read and write + * will communicate with the associated FW client. + * Only in close() (file_operation release()) the communication between + * the clients is disconnected + * + * The IOCTL argument is a struct with a union that contains + * the input parameter and the output parameter for this IOCTL. + * + * The input parameter is UUID of the FW Client. + * The output parameter is the properties of the FW client + * (FW protocol version and max message size). + * + */ +#define IOCTL_MEI_CONNECT_CLIENT \ + _IOWR('H' , 0x01, struct mei_connect_client_data) + +/* + * Intel MEI client information struct + */ +struct mei_client { + __u32 max_msg_length; + __u8 protocol_version; + __u8 reserved[3]; +}; + +/* + * IOCTL Connect Client Data structure + */ +struct mei_connect_client_data { + union { + uuid_le in_client_uuid; + struct mei_client out_client_properties; + }; +}; + +#endif /* _LINUX_MEI_H */ -- cgit v1.2.3-71-gd317 From 67eedba39ed1ac29908453647652c02fbbeeca1b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 11 May 2012 11:36:52 +0200 Subject: iio: core: introduce dB scle: IIO_VAL_INT_PLUS_MICRO_DB Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/industrialio-core.c | 19 +++++++++++++------ include/linux/iio/types.h | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index b39a58757907..425cd4cf31fb 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -295,26 +295,33 @@ static ssize_t iio_read_channel_info(struct device *dev, struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int val, val2; + bool scale_db = false; int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, &val, &val2, this_attr->address); if (ret < 0) return ret; - if (ret == IIO_VAL_INT) + switch (ret) { + case IIO_VAL_INT: return sprintf(buf, "%d\n", val); - else if (ret == IIO_VAL_INT_PLUS_MICRO) { + case IIO_VAL_INT_PLUS_MICRO_DB: + scale_db = true; + case IIO_VAL_INT_PLUS_MICRO: if (val2 < 0) - return sprintf(buf, "-%d.%06u\n", val, -val2); + return sprintf(buf, "-%d.%06u%s\n", val, -val2, + scale_db ? " dB" : ""); else - return sprintf(buf, "%d.%06u\n", val, val2); - } else if (ret == IIO_VAL_INT_PLUS_NANO) { + return sprintf(buf, "%d.%06u%s\n", val, val2, + scale_db ? " dB" : ""); + case IIO_VAL_INT_PLUS_NANO: if (val2 < 0) return sprintf(buf, "-%d.%09u\n", val, -val2); else return sprintf(buf, "%d.%09u\n", val, val2); - } else + default: return 0; + } } static ssize_t iio_write_channel_info(struct device *dev, diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index a471fd5a4d95..1b073b1cc7c2 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -50,5 +50,6 @@ enum iio_modifier { #define IIO_VAL_INT 1 #define IIO_VAL_INT_PLUS_MICRO 2 #define IIO_VAL_INT_PLUS_NANO 3 +#define IIO_VAL_INT_PLUS_MICRO_DB 4 #endif /* _IIO_TYPES_H_ */ -- cgit v1.2.3-71-gd317 From b65d62122fa57035fae06a78e0b65622a1e1bc34 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 11 May 2012 11:36:53 +0200 Subject: iio: core: introduce IIO_CHAN_INFO_HARDWAREGAIN Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-iio | 7 +++++++ drivers/iio/industrialio-core.c | 1 + include/linux/iio/iio.h | 5 +++++ 3 files changed, 13 insertions(+) (limited to 'include/linux') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 2ce4dadaf3f5..5bc8a476c15e 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -280,6 +280,13 @@ Description: If a discrete set of scale values are available, they are listed in this attribute. +What /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain +KernelVersion: 2.6.35 +Contact: linux-iio@vger.kernel.org +Description: + Hardware applied gain factor. If shared across all channels, + _hardwaregain is used. + What: /sys/.../in_accel_filter_low_pass_3db_frequency What: /sys/.../in_magn_filter_low_pass_3db_frequency What: /sys/.../in_anglvel_filter_low_pass_3db_frequency diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 425cd4cf31fb..86f34600a3aa 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -91,6 +91,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency", [IIO_CHAN_INFO_FREQUENCY] = "frequency", [IIO_CHAN_INFO_PHASE] = "phase", + [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", }; const struct iio_chan_spec diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 6fdbdb858e35..897c6b01d784 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -34,6 +34,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_SAMP_FREQ, IIO_CHAN_INFO_FREQUENCY, IIO_CHAN_INFO_PHASE, + IIO_CHAN_INFO_HARDWAREGAIN, }; #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) @@ -95,6 +96,10 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PHASE) #define IIO_CHAN_INFO_PHASE_SHARED_BIT \ IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PHASE) +#define IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_HARDWAREGAIN) +#define IIO_CHAN_INFO_HARDWAREGAIN_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_HARDWAREGAIN) enum iio_endian { IIO_CPU, -- cgit v1.2.3-71-gd317 From aaeb6dfff02f9c1077c2a09c45b99f6255ef9159 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 11 May 2012 15:35:32 +0200 Subject: ARM: AT91: Add platform data for the AT91 ADCs The AT91 SoCs often embeds an ADC. This patch adds the needed platform data to specify the informations required by the driver to work properly. For now, we only need the reference voltage and which channels are available on the board. Signed-off-by: Maxime Ripard Acked-by: Nicolas Ferre Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/platform_data/at91_adc.h | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 include/linux/platform_data/at91_adc.h (limited to 'include/linux') diff --git a/include/linux/platform_data/at91_adc.h b/include/linux/platform_data/at91_adc.h new file mode 100644 index 000000000000..e15745b4f3a5 --- /dev/null +++ b/include/linux/platform_data/at91_adc.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Free Electrons + * + * Licensed under the GPLv2 or later. + */ + +#ifndef _AT91_ADC_H_ +#define _AT91_ADC_H_ + +/** + * struct at91_adc_reg_desc - Various informations relative to registers + * @channel_base: Base offset for the channel data registers + * @drdy_mask: Mask of the DRDY field in the relevant registers + (Interruptions registers mostly) + * @status_register: Offset of the Interrupt Status Register + * @trigger_register: Offset of the Trigger setup register + */ +struct at91_adc_reg_desc { + u8 channel_base; + u32 drdy_mask; + u8 status_register; + u8 trigger_register; +}; + +/** + * struct at91_adc_trigger - description of triggers + * @name: name of the trigger advertised to the user + * @value: value to set in the ADC's trigger setup register + to enable the trigger + * @is_external: Does the trigger rely on an external pin? + */ +struct at91_adc_trigger { + const char *name; + u8 value; + bool is_external; +}; + +/** + * struct at91_adc_data - platform data for ADC driver + * @channels_used: channels in use on the board as a bitmask + * @num_channels: global number of channels available on the board + * @registers: Registers definition on the board + * @startup_time: startup time of the ADC in microseconds + * @trigger_list: Triggers available in the ADC + * @trigger_number: Number of triggers available in the ADC + * @use_external_triggers: does the board has external triggers availables + * @vref: Reference voltage for the ADC in millivolts + */ +struct at91_adc_data { + unsigned long channels_used; + u8 num_channels; + struct at91_adc_reg_desc *registers; + u8 startup_time; + struct at91_adc_trigger *trigger_list; + u8 trigger_number; + bool use_external_triggers; + u16 vref; +}; + +extern void __init at91_add_device_adc(struct at91_adc_data *data); +#endif -- cgit v1.2.3-71-gd317 From 7a7913f11ddf932e20d2bde72bec57f2f7a9b49e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 12 May 2012 15:39:32 +0200 Subject: iio: Add dev_to_iio_dev() helper function This patch adds a helper function for retriving a iio_dev struct from a device struct. Currently we open-code this in two different ways. One is using dev_get_drvdata on the device and the other is using container_of. The new helper function uses the container_of solution as it creates slightly smaller code and also will eventually free up the drvdata pointer for usage by invidual drivers. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- include/linux/iio/iio.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/linux') diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 897c6b01d784..3a4f6a3ab80d 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -427,6 +427,17 @@ static inline void iio_device_put(struct iio_dev *indio_dev) put_device(&indio_dev->dev); }; +/** + * dev_to_iio_dev() - Get IIO device struct from a device struct + * @dev: The device embedded in the IIO device + * + * Note: The device must be a IIO device, otherwise the result is undefined. + */ +static inline struct iio_dev *dev_to_iio_dev(struct device *dev) +{ + return container_of(dev, struct iio_dev, dev); +} + /* Can we make this smaller? */ #define IIO_ALIGN L1_CACHE_BYTES /** -- cgit v1.2.3-71-gd317 From 1894a253db97059bc299b834b76f665bc6586b1d Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Wed, 16 May 2012 05:43:08 -0700 Subject: ramoops: Move to fs/pstore/ram.c Since ramoops was converted to pstore, it has nothing to do with character devices nowadays. Instead, today it is just a RAM backend for pstore. The patch just moves things around. There are a few changes were needed because of the move: 1. Kconfig and Makefiles fixups, of course. 2. In pstore/ram.c we have to play a bit with MODULE_PARAM_PREFIX, this is needed to keep user experience the same as with ramoops driver (i.e. so that ramoops.foo kernel command line arguments would still work). Signed-off-by: Anton Vorontsov Acked-by: Marco Stornelli Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- Documentation/ramoops.txt | 2 +- drivers/char/Kconfig | 9 -- drivers/char/Makefile | 1 - drivers/char/ramoops.c | 362 --------------------------------------------- fs/pstore/Kconfig | 14 ++ fs/pstore/Makefile | 3 + fs/pstore/ram.c | 362 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pstore_ram.h | 17 +++ include/linux/ramoops.h | 17 --- 9 files changed, 397 insertions(+), 390 deletions(-) delete mode 100644 drivers/char/ramoops.c create mode 100644 fs/pstore/ram.c create mode 100644 include/linux/pstore_ram.h delete mode 100644 include/linux/ramoops.h (limited to 'include/linux') diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt index a0b9d8e75380..470d2c4db6ff 100644 --- a/Documentation/ramoops.txt +++ b/Documentation/ramoops.txt @@ -38,7 +38,7 @@ Setting the ramoops parameters can be done in 2 different manners: 2. Use a platform device and set the platform data. The parameters can then be set through that platform data. An example of doing that is: -#include +#include [...] static struct ramoops_platform_data ramoops_data = { diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index fab778d471c5..ea6f6325f9ba 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -585,15 +585,6 @@ config DEVPORT source "drivers/s390/char/Kconfig" -config RAMOOPS - tristate "Log panic/oops to a RAM buffer" - depends on HAS_IOMEM - depends on PSTORE - default n - help - This enables panic and oops messages to be logged to a circular - buffer in RAM where it can be read back at some later point. - config MSM_SMD_PKT bool "Enable device interface for some SMD packet ports" default n diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 0dc5d7ce4864..d0b27a39f1d4 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -58,7 +58,6 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o obj-$(CONFIG_TCG_TPM) += tpm/ obj-$(CONFIG_PS3_FLASH) += ps3flash.o -obj-$(CONFIG_RAMOOPS) += ramoops.o obj-$(CONFIG_JS_RTC) += js-rtc.o js-rtc-y = rtc.o diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c deleted file mode 100644 index b8b8542a5105..000000000000 --- a/drivers/char/ramoops.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * RAM Oops/Panic logger - * - * Copyright (C) 2010 Marco Stornelli - * Copyright (C) 2011 Kees Cook - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RAMOOPS_KERNMSG_HDR "====" -#define MIN_MEM_SIZE 4096UL - -static ulong record_size = MIN_MEM_SIZE; -module_param(record_size, ulong, 0400); -MODULE_PARM_DESC(record_size, - "size of each dump done on oops/panic"); - -static ulong mem_address; -module_param(mem_address, ulong, 0400); -MODULE_PARM_DESC(mem_address, - "start of reserved RAM used to store oops/panic logs"); - -static ulong mem_size; -module_param(mem_size, ulong, 0400); -MODULE_PARM_DESC(mem_size, - "size of reserved RAM used to store oops/panic logs"); - -static int dump_oops = 1; -module_param(dump_oops, int, 0600); -MODULE_PARM_DESC(dump_oops, - "set to 1 to dump oopses, 0 to only dump panics (default 1)"); - -struct ramoops_context { - void *virt_addr; - phys_addr_t phys_addr; - unsigned long size; - size_t record_size; - int dump_oops; - unsigned int count; - unsigned int max_count; - unsigned int read_count; - struct pstore_info pstore; -}; - -static struct platform_device *dummy; -static struct ramoops_platform_data *dummy_data; - -static int ramoops_pstore_open(struct pstore_info *psi) -{ - struct ramoops_context *cxt = psi->data; - - cxt->read_count = 0; - return 0; -} - -static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, - struct timespec *time, - char **buf, - struct pstore_info *psi) -{ - ssize_t size; - char *rambuf; - struct ramoops_context *cxt = psi->data; - - if (cxt->read_count >= cxt->max_count) - return -EINVAL; - *id = cxt->read_count++; - /* Only supports dmesg output so far. */ - *type = PSTORE_TYPE_DMESG; - /* TODO(kees): Bogus time for the moment. */ - time->tv_sec = 0; - time->tv_nsec = 0; - - rambuf = cxt->virt_addr + (*id * cxt->record_size); - size = strnlen(rambuf, cxt->record_size); - *buf = kmalloc(size, GFP_KERNEL); - if (*buf == NULL) - return -ENOMEM; - memcpy(*buf, rambuf, size); - - return size; -} - -static int ramoops_pstore_write(enum pstore_type_id type, - enum kmsg_dump_reason reason, - u64 *id, - unsigned int part, - size_t size, struct pstore_info *psi) -{ - char *buf; - size_t res; - struct timeval timestamp; - struct ramoops_context *cxt = psi->data; - size_t available = cxt->record_size; - - /* Currently ramoops is designed to only store dmesg dumps. */ - if (type != PSTORE_TYPE_DMESG) - return -EINVAL; - - /* Out of the various dmesg dump types, ramoops is currently designed - * to only store crash logs, rather than storing general kernel logs. - */ - if (reason != KMSG_DUMP_OOPS && - reason != KMSG_DUMP_PANIC) - return -EINVAL; - - /* Skip Oopes when configured to do so. */ - if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops) - return -EINVAL; - - /* Explicitly only take the first part of any new crash. - * If our buffer is larger than kmsg_bytes, this can never happen, - * and if our buffer is smaller than kmsg_bytes, we don't want the - * report split across multiple records. - */ - if (part != 1) - return -ENOSPC; - - buf = cxt->virt_addr + (cxt->count * cxt->record_size); - - res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR); - buf += res; - available -= res; - - do_gettimeofday(×tamp); - res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec); - buf += res; - available -= res; - - if (size > available) - size = available; - - memcpy(buf, cxt->pstore.buf, size); - memset(buf + size, '\0', available - size); - - cxt->count = (cxt->count + 1) % cxt->max_count; - - return 0; -} - -static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, - struct pstore_info *psi) -{ - char *buf; - struct ramoops_context *cxt = psi->data; - - if (id >= cxt->max_count) - return -EINVAL; - - buf = cxt->virt_addr + (id * cxt->record_size); - memset(buf, '\0', cxt->record_size); - - return 0; -} - -static struct ramoops_context oops_cxt = { - .pstore = { - .owner = THIS_MODULE, - .name = "ramoops", - .open = ramoops_pstore_open, - .read = ramoops_pstore_read, - .write = ramoops_pstore_write, - .erase = ramoops_pstore_erase, - }, -}; - -static int __init ramoops_probe(struct platform_device *pdev) -{ - struct ramoops_platform_data *pdata = pdev->dev.platform_data; - struct ramoops_context *cxt = &oops_cxt; - int err = -EINVAL; - - /* Only a single ramoops area allowed at a time, so fail extra - * probes. - */ - if (cxt->max_count) - goto fail_out; - - if (!pdata->mem_size || !pdata->record_size) { - pr_err("The memory size and the record size must be " - "non-zero\n"); - goto fail_out; - } - - pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); - pdata->record_size = rounddown_pow_of_two(pdata->record_size); - - /* Check for the minimum memory size */ - if (pdata->mem_size < MIN_MEM_SIZE && - pdata->record_size < MIN_MEM_SIZE) { - pr_err("memory size too small, minimum is %lu\n", - MIN_MEM_SIZE); - goto fail_out; - } - - if (pdata->mem_size < pdata->record_size) { - pr_err("The memory size must be larger than the " - "records size\n"); - goto fail_out; - } - - cxt->max_count = pdata->mem_size / pdata->record_size; - cxt->count = 0; - cxt->size = pdata->mem_size; - cxt->phys_addr = pdata->mem_address; - cxt->record_size = pdata->record_size; - cxt->dump_oops = pdata->dump_oops; - - cxt->pstore.data = cxt; - cxt->pstore.bufsize = cxt->record_size; - cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL); - spin_lock_init(&cxt->pstore.buf_lock); - if (!cxt->pstore.buf) { - pr_err("cannot allocate pstore buffer\n"); - goto fail_clear; - } - - if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { - pr_err("request mem region (0x%lx@0x%llx) failed\n", - cxt->size, (unsigned long long)cxt->phys_addr); - err = -EINVAL; - goto fail_buf; - } - - cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size); - if (!cxt->virt_addr) { - pr_err("ioremap failed\n"); - goto fail_mem_region; - } - - err = pstore_register(&cxt->pstore); - if (err) { - pr_err("registering with pstore failed\n"); - goto fail_iounmap; - } - - /* - * Update the module parameter variables as well so they are visible - * through /sys/module/ramoops/parameters/ - */ - mem_size = pdata->mem_size; - mem_address = pdata->mem_address; - record_size = pdata->record_size; - dump_oops = pdata->dump_oops; - - pr_info("attached 0x%lx@0x%llx (%ux0x%zx)\n", - cxt->size, (unsigned long long)cxt->phys_addr, - cxt->max_count, cxt->record_size); - - return 0; - -fail_iounmap: - iounmap(cxt->virt_addr); -fail_mem_region: - release_mem_region(cxt->phys_addr, cxt->size); -fail_buf: - kfree(cxt->pstore.buf); -fail_clear: - cxt->pstore.bufsize = 0; - cxt->max_count = 0; -fail_out: - return err; -} - -static int __exit ramoops_remove(struct platform_device *pdev) -{ -#if 0 - /* TODO(kees): We cannot unload ramoops since pstore doesn't support - * unregistering yet. - */ - struct ramoops_context *cxt = &oops_cxt; - - iounmap(cxt->virt_addr); - release_mem_region(cxt->phys_addr, cxt->size); - cxt->max_count = 0; - - /* TODO(kees): When pstore supports unregistering, call it here. */ - kfree(cxt->pstore.buf); - cxt->pstore.bufsize = 0; - - return 0; -#endif - return -EBUSY; -} - -static struct platform_driver ramoops_driver = { - .remove = __exit_p(ramoops_remove), - .driver = { - .name = "ramoops", - .owner = THIS_MODULE, - }, -}; - -static int __init ramoops_init(void) -{ - int ret; - ret = platform_driver_probe(&ramoops_driver, ramoops_probe); - if (ret == -ENODEV) { - /* - * If we didn't find a platform device, we use module parameters - * building platform data on the fly. - */ - pr_info("platform device not found, using module parameters\n"); - dummy_data = kzalloc(sizeof(struct ramoops_platform_data), - GFP_KERNEL); - if (!dummy_data) - return -ENOMEM; - dummy_data->mem_size = mem_size; - dummy_data->mem_address = mem_address; - dummy_data->record_size = record_size; - dummy_data->dump_oops = dump_oops; - dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, - NULL, 0, dummy_data, - sizeof(struct ramoops_platform_data)); - - if (IS_ERR(dummy)) - ret = PTR_ERR(dummy); - else - ret = 0; - } - - return ret; -} - -static void __exit ramoops_exit(void) -{ - platform_driver_unregister(&ramoops_driver); - kfree(dummy_data); -} - -module_init(ramoops_init); -module_exit(ramoops_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Marco Stornelli "); -MODULE_DESCRIPTION("RAM Oops/Panic logger/driver"); diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 8007ae7c0d8c..b75ee51b2714 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -11,3 +11,17 @@ config PSTORE (e.g. ACPI_APEI on X86) which will select this for you. If you don't have a platform persistent store driver, say N. + +config PSTORE_RAM + tristate "Log panic/oops to a RAM buffer" + depends on HAS_IOMEM + depends on PSTORE + default n + help + This enables panic and oops messages to be logged to a circular + buffer in RAM where it can be read back at some later point. + + Note that for historical reasons, the module will be named + "ramoops.ko". + + For more information, see Documentation/ramoops.txt. diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile index 760f4bce7d1d..2ab3d0d55ef6 100644 --- a/fs/pstore/Makefile +++ b/fs/pstore/Makefile @@ -5,3 +5,6 @@ obj-y += pstore.o pstore-objs += inode.o platform.o + +ramoops-objs += ram.o +obj-$(CONFIG_PSTORE_RAM) += ramoops.o diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c new file mode 100644 index 000000000000..e443c9c6914f --- /dev/null +++ b/fs/pstore/ram.c @@ -0,0 +1,362 @@ +/* + * RAM Oops/Panic logger + * + * Copyright (C) 2010 Marco Stornelli + * Copyright (C) 2011 Kees Cook + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RAMOOPS_KERNMSG_HDR "====" +#define MIN_MEM_SIZE 4096UL + +static ulong record_size = MIN_MEM_SIZE; +module_param(record_size, ulong, 0400); +MODULE_PARM_DESC(record_size, + "size of each dump done on oops/panic"); + +static ulong mem_address; +module_param(mem_address, ulong, 0400); +MODULE_PARM_DESC(mem_address, + "start of reserved RAM used to store oops/panic logs"); + +static ulong mem_size; +module_param(mem_size, ulong, 0400); +MODULE_PARM_DESC(mem_size, + "size of reserved RAM used to store oops/panic logs"); + +static int dump_oops = 1; +module_param(dump_oops, int, 0600); +MODULE_PARM_DESC(dump_oops, + "set to 1 to dump oopses, 0 to only dump panics (default 1)"); + +struct ramoops_context { + void *virt_addr; + phys_addr_t phys_addr; + unsigned long size; + size_t record_size; + int dump_oops; + unsigned int count; + unsigned int max_count; + unsigned int read_count; + struct pstore_info pstore; +}; + +static struct platform_device *dummy; +static struct ramoops_platform_data *dummy_data; + +static int ramoops_pstore_open(struct pstore_info *psi) +{ + struct ramoops_context *cxt = psi->data; + + cxt->read_count = 0; + return 0; +} + +static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, + struct timespec *time, + char **buf, + struct pstore_info *psi) +{ + ssize_t size; + char *rambuf; + struct ramoops_context *cxt = psi->data; + + if (cxt->read_count >= cxt->max_count) + return -EINVAL; + *id = cxt->read_count++; + /* Only supports dmesg output so far. */ + *type = PSTORE_TYPE_DMESG; + /* TODO(kees): Bogus time for the moment. */ + time->tv_sec = 0; + time->tv_nsec = 0; + + rambuf = cxt->virt_addr + (*id * cxt->record_size); + size = strnlen(rambuf, cxt->record_size); + *buf = kmalloc(size, GFP_KERNEL); + if (*buf == NULL) + return -ENOMEM; + memcpy(*buf, rambuf, size); + + return size; +} + +static int ramoops_pstore_write(enum pstore_type_id type, + enum kmsg_dump_reason reason, + u64 *id, + unsigned int part, + size_t size, struct pstore_info *psi) +{ + char *buf; + size_t res; + struct timeval timestamp; + struct ramoops_context *cxt = psi->data; + size_t available = cxt->record_size; + + /* Currently ramoops is designed to only store dmesg dumps. */ + if (type != PSTORE_TYPE_DMESG) + return -EINVAL; + + /* Out of the various dmesg dump types, ramoops is currently designed + * to only store crash logs, rather than storing general kernel logs. + */ + if (reason != KMSG_DUMP_OOPS && + reason != KMSG_DUMP_PANIC) + return -EINVAL; + + /* Skip Oopes when configured to do so. */ + if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops) + return -EINVAL; + + /* Explicitly only take the first part of any new crash. + * If our buffer is larger than kmsg_bytes, this can never happen, + * and if our buffer is smaller than kmsg_bytes, we don't want the + * report split across multiple records. + */ + if (part != 1) + return -ENOSPC; + + buf = cxt->virt_addr + (cxt->count * cxt->record_size); + + res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR); + buf += res; + available -= res; + + do_gettimeofday(×tamp); + res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec); + buf += res; + available -= res; + + if (size > available) + size = available; + + memcpy(buf, cxt->pstore.buf, size); + memset(buf + size, '\0', available - size); + + cxt->count = (cxt->count + 1) % cxt->max_count; + + return 0; +} + +static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, + struct pstore_info *psi) +{ + char *buf; + struct ramoops_context *cxt = psi->data; + + if (id >= cxt->max_count) + return -EINVAL; + + buf = cxt->virt_addr + (id * cxt->record_size); + memset(buf, '\0', cxt->record_size); + + return 0; +} + +static struct ramoops_context oops_cxt = { + .pstore = { + .owner = THIS_MODULE, + .name = "ramoops", + .open = ramoops_pstore_open, + .read = ramoops_pstore_read, + .write = ramoops_pstore_write, + .erase = ramoops_pstore_erase, + }, +}; + +static int __init ramoops_probe(struct platform_device *pdev) +{ + struct ramoops_platform_data *pdata = pdev->dev.platform_data; + struct ramoops_context *cxt = &oops_cxt; + int err = -EINVAL; + + /* Only a single ramoops area allowed at a time, so fail extra + * probes. + */ + if (cxt->max_count) + goto fail_out; + + if (!pdata->mem_size || !pdata->record_size) { + pr_err("The memory size and the record size must be " + "non-zero\n"); + goto fail_out; + } + + pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); + pdata->record_size = rounddown_pow_of_two(pdata->record_size); + + /* Check for the minimum memory size */ + if (pdata->mem_size < MIN_MEM_SIZE && + pdata->record_size < MIN_MEM_SIZE) { + pr_err("memory size too small, minimum is %lu\n", + MIN_MEM_SIZE); + goto fail_out; + } + + if (pdata->mem_size < pdata->record_size) { + pr_err("The memory size must be larger than the " + "records size\n"); + goto fail_out; + } + + cxt->max_count = pdata->mem_size / pdata->record_size; + cxt->count = 0; + cxt->size = pdata->mem_size; + cxt->phys_addr = pdata->mem_address; + cxt->record_size = pdata->record_size; + cxt->dump_oops = pdata->dump_oops; + + cxt->pstore.data = cxt; + cxt->pstore.bufsize = cxt->record_size; + cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL); + spin_lock_init(&cxt->pstore.buf_lock); + if (!cxt->pstore.buf) { + pr_err("cannot allocate pstore buffer\n"); + goto fail_clear; + } + + if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { + pr_err("request mem region (0x%lx@0x%llx) failed\n", + cxt->size, (unsigned long long)cxt->phys_addr); + err = -EINVAL; + goto fail_buf; + } + + cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size); + if (!cxt->virt_addr) { + pr_err("ioremap failed\n"); + goto fail_mem_region; + } + + err = pstore_register(&cxt->pstore); + if (err) { + pr_err("registering with pstore failed\n"); + goto fail_iounmap; + } + + /* + * Update the module parameter variables as well so they are visible + * through /sys/module/ramoops/parameters/ + */ + mem_size = pdata->mem_size; + mem_address = pdata->mem_address; + record_size = pdata->record_size; + dump_oops = pdata->dump_oops; + + pr_info("attached 0x%lx@0x%llx (%ux0x%zx)\n", + cxt->size, (unsigned long long)cxt->phys_addr, + cxt->max_count, cxt->record_size); + + return 0; + +fail_iounmap: + iounmap(cxt->virt_addr); +fail_mem_region: + release_mem_region(cxt->phys_addr, cxt->size); +fail_buf: + kfree(cxt->pstore.buf); +fail_clear: + cxt->pstore.bufsize = 0; + cxt->max_count = 0; +fail_out: + return err; +} + +static int __exit ramoops_remove(struct platform_device *pdev) +{ +#if 0 + /* TODO(kees): We cannot unload ramoops since pstore doesn't support + * unregistering yet. + */ + struct ramoops_context *cxt = &oops_cxt; + + iounmap(cxt->virt_addr); + release_mem_region(cxt->phys_addr, cxt->size); + cxt->max_count = 0; + + /* TODO(kees): When pstore supports unregistering, call it here. */ + kfree(cxt->pstore.buf); + cxt->pstore.bufsize = 0; + + return 0; +#endif + return -EBUSY; +} + +static struct platform_driver ramoops_driver = { + .remove = __exit_p(ramoops_remove), + .driver = { + .name = "ramoops", + .owner = THIS_MODULE, + }, +}; + +static int __init ramoops_init(void) +{ + int ret; + ret = platform_driver_probe(&ramoops_driver, ramoops_probe); + if (ret == -ENODEV) { + /* + * If we didn't find a platform device, we use module parameters + * building platform data on the fly. + */ + pr_info("platform device not found, using module parameters\n"); + dummy_data = kzalloc(sizeof(struct ramoops_platform_data), + GFP_KERNEL); + if (!dummy_data) + return -ENOMEM; + dummy_data->mem_size = mem_size; + dummy_data->mem_address = mem_address; + dummy_data->record_size = record_size; + dummy_data->dump_oops = dump_oops; + dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, + NULL, 0, dummy_data, + sizeof(struct ramoops_platform_data)); + + if (IS_ERR(dummy)) + ret = PTR_ERR(dummy); + else + ret = 0; + } + + return ret; +} + +static void __exit ramoops_exit(void) +{ + platform_driver_unregister(&ramoops_driver); + kfree(dummy_data); +} + +module_init(ramoops_init); +module_exit(ramoops_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Marco Stornelli "); +MODULE_DESCRIPTION("RAM Oops/Panic logger/driver"); diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h new file mode 100644 index 000000000000..fa4cb02da413 --- /dev/null +++ b/include/linux/pstore_ram.h @@ -0,0 +1,17 @@ +#ifndef __LINUX_PSTORE_RAM_H__ +#define __LINUX_PSTORE_RAM_H__ + +/* + * Ramoops platform data + * @mem_size memory size for ramoops + * @mem_address physical memory address to contain ramoops + */ + +struct ramoops_platform_data { + unsigned long mem_size; + unsigned long mem_address; + unsigned long record_size; + int dump_oops; +}; + +#endif diff --git a/include/linux/ramoops.h b/include/linux/ramoops.h deleted file mode 100644 index 484fef81cd3a..000000000000 --- a/include/linux/ramoops.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __RAMOOPS_H -#define __RAMOOPS_H - -/* - * Ramoops platform data - * @mem_size memory size for ramoops - * @mem_address physical memory address to contain ramoops - */ - -struct ramoops_platform_data { - unsigned long mem_size; - unsigned long mem_address; - unsigned long record_size; - int dump_oops; -}; - -#endif -- cgit v1.2.3-71-gd317 From cddb8751c80348df75149f44fc3bf38d3dd1f3e6 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 17 May 2012 00:15:08 -0700 Subject: staging: android: persistent_ram: Move to fs/pstore/ram_core.c This is a first step for adding ECC support for pstore RAM backend: we will use the persistent_ram routines, kindly provided by Google. Basically, persistent_ram is a set of helper routines to deal with the [optionally] ECC-protected persistent ram regions. A bit of Makefile, Kconfig and header files adjustments were needed because of the move. Signed-off-by: Anton Vorontsov Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/Kconfig | 10 +- drivers/staging/android/Makefile | 1 - drivers/staging/android/persistent_ram.c | 532 ------------------------------- drivers/staging/android/persistent_ram.h | 82 ----- drivers/staging/android/ram_console.c | 2 +- fs/pstore/Kconfig | 7 +- fs/pstore/Makefile | 2 +- fs/pstore/ram_core.c | 532 +++++++++++++++++++++++++++++++ include/linux/pstore_ram.h | 80 +++++ 9 files changed, 620 insertions(+), 628 deletions(-) delete mode 100644 drivers/staging/android/persistent_ram.c delete mode 100644 drivers/staging/android/persistent_ram.h create mode 100644 fs/pstore/ram_core.c (limited to 'include/linux') diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 775229d12569..63f98223760b 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -25,17 +25,9 @@ config ANDROID_LOGGER tristate "Android log driver" default n -config ANDROID_PERSISTENT_RAM - bool - depends on HAVE_MEMBLOCK - select REED_SOLOMON - select REED_SOLOMON_ENC8 - select REED_SOLOMON_DEC8 - config ANDROID_RAM_CONSOLE bool "Android RAM buffer console" - depends on !S390 && !UML && HAVE_MEMBLOCK - select ANDROID_PERSISTENT_RAM + depends on !S390 && !UML && HAVE_MEMBLOCK && PSTORE_RAM=y default n config ANDROID_TIMED_OUTPUT diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index b4be69f80d78..4677e7b0e07a 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -1,7 +1,6 @@ obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_LOGGER) += logger.o -obj-$(CONFIG_ANDROID_PERSISTENT_RAM) += persistent_ram.o obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o diff --git a/drivers/staging/android/persistent_ram.c b/drivers/staging/android/persistent_ram.c deleted file mode 100644 index 4b46eaad5f56..000000000000 --- a/drivers/staging/android/persistent_ram.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright (C) 2012 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "persistent_ram.h" - -struct persistent_ram_buffer { - uint32_t sig; - atomic_t start; - atomic_t size; - uint8_t data[0]; -}; - -#define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */ - -static __initdata LIST_HEAD(persistent_ram_list); - -static inline size_t buffer_size(struct persistent_ram_zone *prz) -{ - return atomic_read(&prz->buffer->size); -} - -static inline size_t buffer_start(struct persistent_ram_zone *prz) -{ - return atomic_read(&prz->buffer->start); -} - -/* increase and wrap the start pointer, returning the old value */ -static inline size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) -{ - int old; - int new; - - do { - old = atomic_read(&prz->buffer->start); - new = old + a; - while (unlikely(new > prz->buffer_size)) - new -= prz->buffer_size; - } while (atomic_cmpxchg(&prz->buffer->start, old, new) != old); - - return old; -} - -/* increase the size counter until it hits the max size */ -static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a) -{ - size_t old; - size_t new; - - if (atomic_read(&prz->buffer->size) == prz->buffer_size) - return; - - do { - old = atomic_read(&prz->buffer->size); - new = old + a; - if (new > prz->buffer_size) - new = prz->buffer_size; - } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old); -} - -static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz, - uint8_t *data, size_t len, uint8_t *ecc) -{ - int i; - uint16_t par[prz->ecc_size]; - - /* Initialize the parity buffer */ - memset(par, 0, sizeof(par)); - encode_rs8(prz->rs_decoder, data, len, par, 0); - for (i = 0; i < prz->ecc_size; i++) - ecc[i] = par[i]; -} - -static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, - void *data, size_t len, uint8_t *ecc) -{ - int i; - uint16_t par[prz->ecc_size]; - - for (i = 0; i < prz->ecc_size; i++) - par[i] = ecc[i]; - return decode_rs8(prz->rs_decoder, data, par, len, - NULL, 0, NULL, 0, NULL); -} - -static void notrace persistent_ram_update_ecc(struct persistent_ram_zone *prz, - unsigned int start, unsigned int count) -{ - struct persistent_ram_buffer *buffer = prz->buffer; - uint8_t *buffer_end = buffer->data + prz->buffer_size; - uint8_t *block; - uint8_t *par; - int ecc_block_size = prz->ecc_block_size; - int ecc_size = prz->ecc_size; - int size = prz->ecc_block_size; - - if (!prz->ecc) - return; - - block = buffer->data + (start & ~(ecc_block_size - 1)); - par = prz->par_buffer + (start / ecc_block_size) * prz->ecc_size; - - do { - if (block + ecc_block_size > buffer_end) - size = buffer_end - block; - persistent_ram_encode_rs8(prz, block, size, par); - block += ecc_block_size; - par += ecc_size; - } while (block < buffer->data + start + count); -} - -static void persistent_ram_update_header_ecc(struct persistent_ram_zone *prz) -{ - struct persistent_ram_buffer *buffer = prz->buffer; - - if (!prz->ecc) - return; - - persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer), - prz->par_header); -} - -static void persistent_ram_ecc_old(struct persistent_ram_zone *prz) -{ - struct persistent_ram_buffer *buffer = prz->buffer; - uint8_t *block; - uint8_t *par; - - if (!prz->ecc) - return; - - block = buffer->data; - par = prz->par_buffer; - while (block < buffer->data + buffer_size(prz)) { - int numerr; - int size = prz->ecc_block_size; - if (block + size > buffer->data + prz->buffer_size) - size = buffer->data + prz->buffer_size - block; - numerr = persistent_ram_decode_rs8(prz, block, size, par); - if (numerr > 0) { - pr_devel("persistent_ram: error in block %p, %d\n", - block, numerr); - prz->corrected_bytes += numerr; - } else if (numerr < 0) { - pr_devel("persistent_ram: uncorrectable error in block %p\n", - block); - prz->bad_blocks++; - } - block += prz->ecc_block_size; - par += prz->ecc_size; - } -} - -static int persistent_ram_init_ecc(struct persistent_ram_zone *prz, - size_t buffer_size) -{ - int numerr; - struct persistent_ram_buffer *buffer = prz->buffer; - int ecc_blocks; - - if (!prz->ecc) - return 0; - - prz->ecc_block_size = 128; - prz->ecc_size = 16; - prz->ecc_symsize = 8; - prz->ecc_poly = 0x11d; - - ecc_blocks = DIV_ROUND_UP(prz->buffer_size, prz->ecc_block_size); - prz->buffer_size -= (ecc_blocks + 1) * prz->ecc_size; - - if (prz->buffer_size > buffer_size) { - pr_err("persistent_ram: invalid size %zu, non-ecc datasize %zu\n", - buffer_size, prz->buffer_size); - return -EINVAL; - } - - prz->par_buffer = buffer->data + prz->buffer_size; - prz->par_header = prz->par_buffer + ecc_blocks * prz->ecc_size; - - /* - * first consecutive root is 0 - * primitive element to generate roots = 1 - */ - prz->rs_decoder = init_rs(prz->ecc_symsize, prz->ecc_poly, 0, 1, - prz->ecc_size); - if (prz->rs_decoder == NULL) { - pr_info("persistent_ram: init_rs failed\n"); - return -EINVAL; - } - - prz->corrected_bytes = 0; - prz->bad_blocks = 0; - - numerr = persistent_ram_decode_rs8(prz, buffer, sizeof(*buffer), - prz->par_header); - if (numerr > 0) { - pr_info("persistent_ram: error in header, %d\n", numerr); - prz->corrected_bytes += numerr; - } else if (numerr < 0) { - pr_info("persistent_ram: uncorrectable error in header\n"); - prz->bad_blocks++; - } - - return 0; -} - -ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, - char *str, size_t len) -{ - ssize_t ret; - - if (prz->corrected_bytes || prz->bad_blocks) - ret = snprintf(str, len, "" - "\n%d Corrected bytes, %d unrecoverable blocks\n", - prz->corrected_bytes, prz->bad_blocks); - else - ret = snprintf(str, len, "\nNo errors detected\n"); - - return ret; -} - -static void notrace persistent_ram_update(struct persistent_ram_zone *prz, - const void *s, unsigned int start, unsigned int count) -{ - struct persistent_ram_buffer *buffer = prz->buffer; - memcpy(buffer->data + start, s, count); - persistent_ram_update_ecc(prz, start, count); -} - -static void __init -persistent_ram_save_old(struct persistent_ram_zone *prz) -{ - struct persistent_ram_buffer *buffer = prz->buffer; - size_t size = buffer_size(prz); - size_t start = buffer_start(prz); - char *dest; - - persistent_ram_ecc_old(prz); - - dest = kmalloc(size, GFP_KERNEL); - if (dest == NULL) { - pr_err("persistent_ram: failed to allocate buffer\n"); - return; - } - - prz->old_log = dest; - prz->old_log_size = size; - memcpy(prz->old_log, &buffer->data[start], size - start); - memcpy(prz->old_log + size - start, &buffer->data[0], start); -} - -int notrace persistent_ram_write(struct persistent_ram_zone *prz, - const void *s, unsigned int count) -{ - int rem; - int c = count; - size_t start; - - if (unlikely(c > prz->buffer_size)) { - s += c - prz->buffer_size; - c = prz->buffer_size; - } - - buffer_size_add(prz, c); - - start = buffer_start_add(prz, c); - - rem = prz->buffer_size - start; - if (unlikely(rem < c)) { - persistent_ram_update(prz, s, start, rem); - s += rem; - c -= rem; - start = 0; - } - persistent_ram_update(prz, s, start, c); - - persistent_ram_update_header_ecc(prz); - - return count; -} - -size_t persistent_ram_old_size(struct persistent_ram_zone *prz) -{ - return prz->old_log_size; -} - -void *persistent_ram_old(struct persistent_ram_zone *prz) -{ - return prz->old_log; -} - -void persistent_ram_free_old(struct persistent_ram_zone *prz) -{ - kfree(prz->old_log); - prz->old_log = NULL; - prz->old_log_size = 0; -} - -static void *persistent_ram_vmap(phys_addr_t start, size_t size) -{ - struct page **pages; - phys_addr_t page_start; - unsigned int page_count; - pgprot_t prot; - unsigned int i; - void *vaddr; - - page_start = start - offset_in_page(start); - page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); - - prot = pgprot_noncached(PAGE_KERNEL); - - pages = kmalloc(sizeof(struct page *) * page_count, GFP_KERNEL); - if (!pages) { - pr_err("%s: Failed to allocate array for %u pages\n", __func__, - page_count); - return NULL; - } - - for (i = 0; i < page_count; i++) { - phys_addr_t addr = page_start + i * PAGE_SIZE; - pages[i] = pfn_to_page(addr >> PAGE_SHIFT); - } - vaddr = vmap(pages, page_count, VM_MAP, prot); - kfree(pages); - - return vaddr; -} - -static void *persistent_ram_iomap(phys_addr_t start, size_t size) -{ - if (!request_mem_region(start, size, "persistent_ram")) { - pr_err("request mem region (0x%llx@0x%llx) failed\n", - (unsigned long long)size, (unsigned long long)start); - return NULL; - } - - return ioremap(start, size); -} - -static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, - struct persistent_ram_zone *prz) -{ - prz->paddr = start; - prz->size = size; - - if (pfn_valid(start >> PAGE_SHIFT)) - prz->vaddr = persistent_ram_vmap(start, size); - else - prz->vaddr = persistent_ram_iomap(start, size); - - if (!prz->vaddr) { - pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__, - (unsigned long long)size, (unsigned long long)start); - return -ENOMEM; - } - - prz->buffer = prz->vaddr + offset_in_page(start); - prz->buffer_size = size - sizeof(struct persistent_ram_buffer); - - return 0; -} - -static int __init persistent_ram_post_init(struct persistent_ram_zone *prz, bool ecc) -{ - int ret; - - prz->ecc = ecc; - - ret = persistent_ram_init_ecc(prz, prz->buffer_size); - if (ret) - return ret; - - if (prz->buffer->sig == PERSISTENT_RAM_SIG) { - if (buffer_size(prz) > prz->buffer_size || - buffer_start(prz) > buffer_size(prz)) - pr_info("persistent_ram: found existing invalid buffer," - " size %zu, start %zu\n", - buffer_size(prz), buffer_start(prz)); - else { - pr_info("persistent_ram: found existing buffer," - " size %zu, start %zu\n", - buffer_size(prz), buffer_start(prz)); - persistent_ram_save_old(prz); - } - } else { - pr_info("persistent_ram: no valid data in buffer" - " (sig = 0x%08x)\n", prz->buffer->sig); - } - - prz->buffer->sig = PERSISTENT_RAM_SIG; - atomic_set(&prz->buffer->start, 0); - atomic_set(&prz->buffer->size, 0); - - return 0; -} - -void persistent_ram_free(struct persistent_ram_zone *prz) -{ - if (pfn_valid(prz->paddr >> PAGE_SHIFT)) { - vunmap(prz->vaddr); - } else { - iounmap(prz->vaddr); - release_mem_region(prz->paddr, prz->size); - } - persistent_ram_free_old(prz); - kfree(prz); -} - -struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, - size_t size, - bool ecc) -{ - struct persistent_ram_zone *prz; - int ret = -ENOMEM; - - prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); - if (!prz) { - pr_err("persistent_ram: failed to allocate persistent ram zone\n"); - goto err; - } - - ret = persistent_ram_buffer_map(start, size, prz); - if (ret) - goto err; - - persistent_ram_post_init(prz, ecc); - persistent_ram_update_header_ecc(prz); - - return prz; -err: - kfree(prz); - return ERR_PTR(ret); -} - -#ifndef MODULE -static int __init persistent_ram_buffer_init(const char *name, - struct persistent_ram_zone *prz) -{ - int i; - struct persistent_ram *ram; - struct persistent_ram_descriptor *desc; - phys_addr_t start; - - list_for_each_entry(ram, &persistent_ram_list, node) { - start = ram->start; - for (i = 0; i < ram->num_descs; i++) { - desc = &ram->descs[i]; - if (!strcmp(desc->name, name)) - return persistent_ram_buffer_map(start, - desc->size, prz); - start += desc->size; - } - } - - return -EINVAL; -} - -static __init -struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc) -{ - struct persistent_ram_zone *prz; - int ret = -ENOMEM; - - prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); - if (!prz) { - pr_err("persistent_ram: failed to allocate persistent ram zone\n"); - goto err; - } - - ret = persistent_ram_buffer_init(dev_name(dev), prz); - if (ret) { - pr_err("persistent_ram: failed to initialize buffer\n"); - goto err; - } - - persistent_ram_post_init(prz, ecc); - - return prz; -err: - kfree(prz); - return ERR_PTR(ret); -} - -struct persistent_ram_zone * __init -persistent_ram_init_ringbuffer(struct device *dev, bool ecc) -{ - return __persistent_ram_init(dev, ecc); -} - -int __init persistent_ram_early_init(struct persistent_ram *ram) -{ - int ret; - - ret = memblock_reserve(ram->start, ram->size); - if (ret) { - pr_err("Failed to reserve persistent memory from %08lx-%08lx\n", - (long)ram->start, (long)(ram->start + ram->size - 1)); - return ret; - } - - list_add_tail(&ram->node, &persistent_ram_list); - - pr_info("Initialized persistent memory from %08lx-%08lx\n", - (long)ram->start, (long)(ram->start + ram->size - 1)); - - return 0; -} -#endif diff --git a/drivers/staging/android/persistent_ram.h b/drivers/staging/android/persistent_ram.h deleted file mode 100644 index d23850ce3ca4..000000000000 --- a/drivers/staging/android/persistent_ram.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __LINUX_PERSISTENT_RAM_H__ -#define __LINUX_PERSISTENT_RAM_H__ - -#include -#include -#include -#include -#include - -struct persistent_ram_buffer; - -struct persistent_ram_descriptor { - const char *name; - phys_addr_t size; -}; - -struct persistent_ram { - phys_addr_t start; - phys_addr_t size; - - int num_descs; - struct persistent_ram_descriptor *descs; - - struct list_head node; -}; - -struct persistent_ram_zone { - phys_addr_t paddr; - size_t size; - void *vaddr; - struct persistent_ram_buffer *buffer; - size_t buffer_size; - - /* ECC correction */ - bool ecc; - char *par_buffer; - char *par_header; - struct rs_control *rs_decoder; - int corrected_bytes; - int bad_blocks; - int ecc_block_size; - int ecc_size; - int ecc_symsize; - int ecc_poly; - - char *old_log; - size_t old_log_size; -}; - -int persistent_ram_early_init(struct persistent_ram *ram); - -struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, - size_t size, - bool ecc); -void persistent_ram_free(struct persistent_ram_zone *prz); -struct persistent_ram_zone *persistent_ram_init_ringbuffer(struct device *dev, - bool ecc); - -int persistent_ram_write(struct persistent_ram_zone *prz, const void *s, - unsigned int count); - -size_t persistent_ram_old_size(struct persistent_ram_zone *prz); -void *persistent_ram_old(struct persistent_ram_zone *prz); -void persistent_ram_free_old(struct persistent_ram_zone *prz); -ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, - char *str, size_t len); - -#endif diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c index ce140ffc54ea..82323bb1d1a3 100644 --- a/drivers/staging/android/ram_console.c +++ b/drivers/staging/android/ram_console.c @@ -21,7 +21,7 @@ #include #include #include -#include "persistent_ram.h" +#include #include "ram_console.h" static struct persistent_ram_zone *ram_console_zone; diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index b75ee51b2714..23ade2680a4a 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -14,9 +14,12 @@ config PSTORE config PSTORE_RAM tristate "Log panic/oops to a RAM buffer" - depends on HAS_IOMEM depends on PSTORE - default n + depends on HAS_IOMEM + depends on HAVE_MEMBLOCK + select REED_SOLOMON + select REED_SOLOMON_ENC8 + select REED_SOLOMON_DEC8 help This enables panic and oops messages to be logged to a circular buffer in RAM where it can be read back at some later point. diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile index 2ab3d0d55ef6..278a44e0d4e1 100644 --- a/fs/pstore/Makefile +++ b/fs/pstore/Makefile @@ -6,5 +6,5 @@ obj-y += pstore.o pstore-objs += inode.o platform.o -ramoops-objs += ram.o +ramoops-objs += ram.o ram_core.o obj-$(CONFIG_PSTORE_RAM) += ramoops.o diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c new file mode 100644 index 000000000000..31f8d184f3a0 --- /dev/null +++ b/fs/pstore/ram_core.c @@ -0,0 +1,532 @@ +/* + * Copyright (C) 2012 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct persistent_ram_buffer { + uint32_t sig; + atomic_t start; + atomic_t size; + uint8_t data[0]; +}; + +#define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */ + +static __initdata LIST_HEAD(persistent_ram_list); + +static inline size_t buffer_size(struct persistent_ram_zone *prz) +{ + return atomic_read(&prz->buffer->size); +} + +static inline size_t buffer_start(struct persistent_ram_zone *prz) +{ + return atomic_read(&prz->buffer->start); +} + +/* increase and wrap the start pointer, returning the old value */ +static inline size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) +{ + int old; + int new; + + do { + old = atomic_read(&prz->buffer->start); + new = old + a; + while (unlikely(new > prz->buffer_size)) + new -= prz->buffer_size; + } while (atomic_cmpxchg(&prz->buffer->start, old, new) != old); + + return old; +} + +/* increase the size counter until it hits the max size */ +static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a) +{ + size_t old; + size_t new; + + if (atomic_read(&prz->buffer->size) == prz->buffer_size) + return; + + do { + old = atomic_read(&prz->buffer->size); + new = old + a; + if (new > prz->buffer_size) + new = prz->buffer_size; + } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old); +} + +static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz, + uint8_t *data, size_t len, uint8_t *ecc) +{ + int i; + uint16_t par[prz->ecc_size]; + + /* Initialize the parity buffer */ + memset(par, 0, sizeof(par)); + encode_rs8(prz->rs_decoder, data, len, par, 0); + for (i = 0; i < prz->ecc_size; i++) + ecc[i] = par[i]; +} + +static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, + void *data, size_t len, uint8_t *ecc) +{ + int i; + uint16_t par[prz->ecc_size]; + + for (i = 0; i < prz->ecc_size; i++) + par[i] = ecc[i]; + return decode_rs8(prz->rs_decoder, data, par, len, + NULL, 0, NULL, 0, NULL); +} + +static void notrace persistent_ram_update_ecc(struct persistent_ram_zone *prz, + unsigned int start, unsigned int count) +{ + struct persistent_ram_buffer *buffer = prz->buffer; + uint8_t *buffer_end = buffer->data + prz->buffer_size; + uint8_t *block; + uint8_t *par; + int ecc_block_size = prz->ecc_block_size; + int ecc_size = prz->ecc_size; + int size = prz->ecc_block_size; + + if (!prz->ecc) + return; + + block = buffer->data + (start & ~(ecc_block_size - 1)); + par = prz->par_buffer + (start / ecc_block_size) * prz->ecc_size; + + do { + if (block + ecc_block_size > buffer_end) + size = buffer_end - block; + persistent_ram_encode_rs8(prz, block, size, par); + block += ecc_block_size; + par += ecc_size; + } while (block < buffer->data + start + count); +} + +static void persistent_ram_update_header_ecc(struct persistent_ram_zone *prz) +{ + struct persistent_ram_buffer *buffer = prz->buffer; + + if (!prz->ecc) + return; + + persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer), + prz->par_header); +} + +static void persistent_ram_ecc_old(struct persistent_ram_zone *prz) +{ + struct persistent_ram_buffer *buffer = prz->buffer; + uint8_t *block; + uint8_t *par; + + if (!prz->ecc) + return; + + block = buffer->data; + par = prz->par_buffer; + while (block < buffer->data + buffer_size(prz)) { + int numerr; + int size = prz->ecc_block_size; + if (block + size > buffer->data + prz->buffer_size) + size = buffer->data + prz->buffer_size - block; + numerr = persistent_ram_decode_rs8(prz, block, size, par); + if (numerr > 0) { + pr_devel("persistent_ram: error in block %p, %d\n", + block, numerr); + prz->corrected_bytes += numerr; + } else if (numerr < 0) { + pr_devel("persistent_ram: uncorrectable error in block %p\n", + block); + prz->bad_blocks++; + } + block += prz->ecc_block_size; + par += prz->ecc_size; + } +} + +static int persistent_ram_init_ecc(struct persistent_ram_zone *prz, + size_t buffer_size) +{ + int numerr; + struct persistent_ram_buffer *buffer = prz->buffer; + int ecc_blocks; + + if (!prz->ecc) + return 0; + + prz->ecc_block_size = 128; + prz->ecc_size = 16; + prz->ecc_symsize = 8; + prz->ecc_poly = 0x11d; + + ecc_blocks = DIV_ROUND_UP(prz->buffer_size, prz->ecc_block_size); + prz->buffer_size -= (ecc_blocks + 1) * prz->ecc_size; + + if (prz->buffer_size > buffer_size) { + pr_err("persistent_ram: invalid size %zu, non-ecc datasize %zu\n", + buffer_size, prz->buffer_size); + return -EINVAL; + } + + prz->par_buffer = buffer->data + prz->buffer_size; + prz->par_header = prz->par_buffer + ecc_blocks * prz->ecc_size; + + /* + * first consecutive root is 0 + * primitive element to generate roots = 1 + */ + prz->rs_decoder = init_rs(prz->ecc_symsize, prz->ecc_poly, 0, 1, + prz->ecc_size); + if (prz->rs_decoder == NULL) { + pr_info("persistent_ram: init_rs failed\n"); + return -EINVAL; + } + + prz->corrected_bytes = 0; + prz->bad_blocks = 0; + + numerr = persistent_ram_decode_rs8(prz, buffer, sizeof(*buffer), + prz->par_header); + if (numerr > 0) { + pr_info("persistent_ram: error in header, %d\n", numerr); + prz->corrected_bytes += numerr; + } else if (numerr < 0) { + pr_info("persistent_ram: uncorrectable error in header\n"); + prz->bad_blocks++; + } + + return 0; +} + +ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, + char *str, size_t len) +{ + ssize_t ret; + + if (prz->corrected_bytes || prz->bad_blocks) + ret = snprintf(str, len, "" + "\n%d Corrected bytes, %d unrecoverable blocks\n", + prz->corrected_bytes, prz->bad_blocks); + else + ret = snprintf(str, len, "\nNo errors detected\n"); + + return ret; +} + +static void notrace persistent_ram_update(struct persistent_ram_zone *prz, + const void *s, unsigned int start, unsigned int count) +{ + struct persistent_ram_buffer *buffer = prz->buffer; + memcpy(buffer->data + start, s, count); + persistent_ram_update_ecc(prz, start, count); +} + +static void __init +persistent_ram_save_old(struct persistent_ram_zone *prz) +{ + struct persistent_ram_buffer *buffer = prz->buffer; + size_t size = buffer_size(prz); + size_t start = buffer_start(prz); + char *dest; + + persistent_ram_ecc_old(prz); + + dest = kmalloc(size, GFP_KERNEL); + if (dest == NULL) { + pr_err("persistent_ram: failed to allocate buffer\n"); + return; + } + + prz->old_log = dest; + prz->old_log_size = size; + memcpy(prz->old_log, &buffer->data[start], size - start); + memcpy(prz->old_log + size - start, &buffer->data[0], start); +} + +int notrace persistent_ram_write(struct persistent_ram_zone *prz, + const void *s, unsigned int count) +{ + int rem; + int c = count; + size_t start; + + if (unlikely(c > prz->buffer_size)) { + s += c - prz->buffer_size; + c = prz->buffer_size; + } + + buffer_size_add(prz, c); + + start = buffer_start_add(prz, c); + + rem = prz->buffer_size - start; + if (unlikely(rem < c)) { + persistent_ram_update(prz, s, start, rem); + s += rem; + c -= rem; + start = 0; + } + persistent_ram_update(prz, s, start, c); + + persistent_ram_update_header_ecc(prz); + + return count; +} + +size_t persistent_ram_old_size(struct persistent_ram_zone *prz) +{ + return prz->old_log_size; +} + +void *persistent_ram_old(struct persistent_ram_zone *prz) +{ + return prz->old_log; +} + +void persistent_ram_free_old(struct persistent_ram_zone *prz) +{ + kfree(prz->old_log); + prz->old_log = NULL; + prz->old_log_size = 0; +} + +static void *persistent_ram_vmap(phys_addr_t start, size_t size) +{ + struct page **pages; + phys_addr_t page_start; + unsigned int page_count; + pgprot_t prot; + unsigned int i; + void *vaddr; + + page_start = start - offset_in_page(start); + page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); + + prot = pgprot_noncached(PAGE_KERNEL); + + pages = kmalloc(sizeof(struct page *) * page_count, GFP_KERNEL); + if (!pages) { + pr_err("%s: Failed to allocate array for %u pages\n", __func__, + page_count); + return NULL; + } + + for (i = 0; i < page_count; i++) { + phys_addr_t addr = page_start + i * PAGE_SIZE; + pages[i] = pfn_to_page(addr >> PAGE_SHIFT); + } + vaddr = vmap(pages, page_count, VM_MAP, prot); + kfree(pages); + + return vaddr; +} + +static void *persistent_ram_iomap(phys_addr_t start, size_t size) +{ + if (!request_mem_region(start, size, "persistent_ram")) { + pr_err("request mem region (0x%llx@0x%llx) failed\n", + (unsigned long long)size, (unsigned long long)start); + return NULL; + } + + return ioremap(start, size); +} + +static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, + struct persistent_ram_zone *prz) +{ + prz->paddr = start; + prz->size = size; + + if (pfn_valid(start >> PAGE_SHIFT)) + prz->vaddr = persistent_ram_vmap(start, size); + else + prz->vaddr = persistent_ram_iomap(start, size); + + if (!prz->vaddr) { + pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__, + (unsigned long long)size, (unsigned long long)start); + return -ENOMEM; + } + + prz->buffer = prz->vaddr + offset_in_page(start); + prz->buffer_size = size - sizeof(struct persistent_ram_buffer); + + return 0; +} + +static int __init persistent_ram_post_init(struct persistent_ram_zone *prz, bool ecc) +{ + int ret; + + prz->ecc = ecc; + + ret = persistent_ram_init_ecc(prz, prz->buffer_size); + if (ret) + return ret; + + if (prz->buffer->sig == PERSISTENT_RAM_SIG) { + if (buffer_size(prz) > prz->buffer_size || + buffer_start(prz) > buffer_size(prz)) + pr_info("persistent_ram: found existing invalid buffer," + " size %zu, start %zu\n", + buffer_size(prz), buffer_start(prz)); + else { + pr_info("persistent_ram: found existing buffer," + " size %zu, start %zu\n", + buffer_size(prz), buffer_start(prz)); + persistent_ram_save_old(prz); + } + } else { + pr_info("persistent_ram: no valid data in buffer" + " (sig = 0x%08x)\n", prz->buffer->sig); + } + + prz->buffer->sig = PERSISTENT_RAM_SIG; + atomic_set(&prz->buffer->start, 0); + atomic_set(&prz->buffer->size, 0); + + return 0; +} + +void persistent_ram_free(struct persistent_ram_zone *prz) +{ + if (pfn_valid(prz->paddr >> PAGE_SHIFT)) { + vunmap(prz->vaddr); + } else { + iounmap(prz->vaddr); + release_mem_region(prz->paddr, prz->size); + } + persistent_ram_free_old(prz); + kfree(prz); +} + +struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, + size_t size, + bool ecc) +{ + struct persistent_ram_zone *prz; + int ret = -ENOMEM; + + prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); + if (!prz) { + pr_err("persistent_ram: failed to allocate persistent ram zone\n"); + goto err; + } + + ret = persistent_ram_buffer_map(start, size, prz); + if (ret) + goto err; + + persistent_ram_post_init(prz, ecc); + persistent_ram_update_header_ecc(prz); + + return prz; +err: + kfree(prz); + return ERR_PTR(ret); +} + +#ifndef MODULE +static int __init persistent_ram_buffer_init(const char *name, + struct persistent_ram_zone *prz) +{ + int i; + struct persistent_ram *ram; + struct persistent_ram_descriptor *desc; + phys_addr_t start; + + list_for_each_entry(ram, &persistent_ram_list, node) { + start = ram->start; + for (i = 0; i < ram->num_descs; i++) { + desc = &ram->descs[i]; + if (!strcmp(desc->name, name)) + return persistent_ram_buffer_map(start, + desc->size, prz); + start += desc->size; + } + } + + return -EINVAL; +} + +static __init +struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc) +{ + struct persistent_ram_zone *prz; + int ret = -ENOMEM; + + prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); + if (!prz) { + pr_err("persistent_ram: failed to allocate persistent ram zone\n"); + goto err; + } + + ret = persistent_ram_buffer_init(dev_name(dev), prz); + if (ret) { + pr_err("persistent_ram: failed to initialize buffer\n"); + goto err; + } + + persistent_ram_post_init(prz, ecc); + + return prz; +err: + kfree(prz); + return ERR_PTR(ret); +} + +struct persistent_ram_zone * __init +persistent_ram_init_ringbuffer(struct device *dev, bool ecc) +{ + return __persistent_ram_init(dev, ecc); +} + +int __init persistent_ram_early_init(struct persistent_ram *ram) +{ + int ret; + + ret = memblock_reserve(ram->start, ram->size); + if (ret) { + pr_err("Failed to reserve persistent memory from %08lx-%08lx\n", + (long)ram->start, (long)(ram->start + ram->size - 1)); + return ret; + } + + list_add_tail(&ram->node, &persistent_ram_list); + + pr_info("Initialized persistent memory from %08lx-%08lx\n", + (long)ram->start, (long)(ram->start + ram->size - 1)); + + return 0; +} +#endif diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index fa4cb02da413..ffe24a52c5af 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -1,6 +1,86 @@ +/* + * Copyright (C) 2010 Marco Stornelli + * Copyright (C) 2011 Kees Cook + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + #ifndef __LINUX_PSTORE_RAM_H__ #define __LINUX_PSTORE_RAM_H__ +#include +#include +#include +#include +#include + +struct persistent_ram_buffer; + +struct persistent_ram_descriptor { + const char *name; + phys_addr_t size; +}; + +struct persistent_ram { + phys_addr_t start; + phys_addr_t size; + + int num_descs; + struct persistent_ram_descriptor *descs; + + struct list_head node; +}; + +struct persistent_ram_zone { + phys_addr_t paddr; + size_t size; + void *vaddr; + struct persistent_ram_buffer *buffer; + size_t buffer_size; + + /* ECC correction */ + bool ecc; + char *par_buffer; + char *par_header; + struct rs_control *rs_decoder; + int corrected_bytes; + int bad_blocks; + int ecc_block_size; + int ecc_size; + int ecc_symsize; + int ecc_poly; + + char *old_log; + size_t old_log_size; +}; + +int persistent_ram_early_init(struct persistent_ram *ram); + +struct persistent_ram_zone * __init persistent_ram_new(phys_addr_t start, + size_t size, + bool ecc); +void persistent_ram_free(struct persistent_ram_zone *prz); +struct persistent_ram_zone *persistent_ram_init_ringbuffer(struct device *dev, + bool ecc); + +int persistent_ram_write(struct persistent_ram_zone *prz, const void *s, + unsigned int count); + +size_t persistent_ram_old_size(struct persistent_ram_zone *prz); +void *persistent_ram_old(struct persistent_ram_zone *prz); +void persistent_ram_free_old(struct persistent_ram_zone *prz); +ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, + char *str, size_t len); + /* * Ramoops platform data * @mem_size memory size for ramoops -- cgit v1.2.3-71-gd317 From 39eb7e9791866973dbb7a3a6d2061d70356c7d90 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 17 May 2012 00:15:34 -0700 Subject: pstore/ram: Add ECC support This is now straightforward: just introduce a module parameter and pass the needed value to persistent_ram_new(). Signed-off-by: Anton Vorontsov Acked-by: Marco Stornelli Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- Documentation/ramoops.txt | 6 ++++++ fs/pstore/ram.c | 15 ++++++++++++--- include/linux/pstore_ram.h | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt index 470d2c4db6ff..4ba7db231cb2 100644 --- a/Documentation/ramoops.txt +++ b/Documentation/ramoops.txt @@ -30,6 +30,11 @@ variable while setting 0 in that variable dumps only the panics. The module uses a counter to record multiple dumps but the counter gets reset on restart (i.e. new dumps after the restart will overwrite old ones). +Ramoops also supports software ECC protection of persistent memory regions. +This might be useful when a hardware reset was used to bring the machine back +to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat +corrupt, but usually it is restorable. + 2. Setting the parameters Setting the ramoops parameters can be done in 2 different manners: @@ -46,6 +51,7 @@ static struct ramoops_platform_data ramoops_data = { .mem_address = <...>, .record_size = <...>, .dump_oops = <...>, + .ecc = <...>, }; static struct platform_device ramoops_dev = { diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 62b13eda4691..9123cce28c1e 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -56,12 +56,18 @@ module_param(dump_oops, int, 0600); MODULE_PARM_DESC(dump_oops, "set to 1 to dump oopses, 0 to only dump panics (default 1)"); +static int ramoops_ecc; +module_param_named(ecc, ramoops_ecc, int, 0600); +MODULE_PARM_DESC(ramoops_ecc, + "set to 1 to enable ECC support"); + struct ramoops_context { struct persistent_ram_zone **przs; phys_addr_t phys_addr; unsigned long size; size_t record_size; int dump_oops; + bool ecc; unsigned int count; unsigned int max_count; unsigned int read_count; @@ -236,6 +242,7 @@ static int __init ramoops_probe(struct platform_device *pdev) cxt->phys_addr = pdata->mem_address; cxt->record_size = pdata->record_size; cxt->dump_oops = pdata->dump_oops; + cxt->ecc = pdata->ecc; cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_count, GFP_KERNEL); if (!cxt->przs) { @@ -248,7 +255,7 @@ static int __init ramoops_probe(struct platform_device *pdev) size_t sz = cxt->record_size; phys_addr_t start = cxt->phys_addr + sz * i; - cxt->przs[i] = persistent_ram_new(start, sz, 0); + cxt->przs[i] = persistent_ram_new(start, sz, cxt->ecc); if (IS_ERR(cxt->przs[i])) { err = PTR_ERR(cxt->przs[i]); dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", @@ -281,9 +288,10 @@ static int __init ramoops_probe(struct platform_device *pdev) record_size = pdata->record_size; dump_oops = pdata->dump_oops; - pr_info("attached 0x%lx@0x%llx (%ux0x%zx)\n", + pr_info("attached 0x%lx@0x%llx (%ux0x%zx), ecc: %s\n", cxt->size, (unsigned long long)cxt->phys_addr, - cxt->max_count, cxt->record_size); + cxt->max_count, cxt->record_size, + ramoops_ecc ? "on" : "off"); return 0; @@ -347,6 +355,7 @@ static int __init ramoops_init(void) dummy_data->mem_address = mem_address; dummy_data->record_size = record_size; dummy_data->dump_oops = dump_oops; + dummy_data->ecc = ramoops_ecc; dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, NULL, 0, dummy_data, sizeof(struct ramoops_platform_data)); diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index ffe24a52c5af..7ed7fd4dba49 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -92,6 +92,7 @@ struct ramoops_platform_data { unsigned long mem_address; unsigned long record_size; int dump_oops; + bool ecc; }; #endif -- cgit v1.2.3-71-gd317