2121#include <linux/types.h>
2222#include <linux/spinlock.h>
2323
24+ #include <asm/unaligned.h>
25+
2426#define QUAD8_EXTENT 32
2527
2628static unsigned int base [max_num_isa_dev (QUAD8_EXTENT )];
@@ -232,52 +234,60 @@ static int quad8_count_read(struct counter_device *counter,
232234 struct quad8 * const priv = counter_priv (counter );
233235 struct channel_reg __iomem * const chan = priv -> reg -> channel + count -> id ;
234236 unsigned long irqflags ;
235- int i ;
236-
237- * val = 0 ;
237+ u8 value [3 ];
238238
239239 spin_lock_irqsave (& priv -> lock , irqflags );
240240
241241 iowrite8 (SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL , & chan -> control );
242-
243- for (i = 0 ; i < 3 ; i ++ )
244- * val |= (unsigned long )ioread8 (& chan -> data ) << (8 * i );
242+ ioread8_rep (& chan -> data , value , sizeof (value ));
245243
246244 spin_unlock_irqrestore (& priv -> lock , irqflags );
247245
246+ * val = get_unaligned_le24 (value );
247+
248248 return 0 ;
249249}
250250
251+ static void quad8_preset_register_set (struct quad8 * const priv , const size_t id ,
252+ const unsigned long preset )
253+ {
254+ struct channel_reg __iomem * const chan = priv -> reg -> channel + id ;
255+ u8 value [3 ];
256+
257+ put_unaligned_le24 (preset , value );
258+
259+ iowrite8 (SELECT_RLD | RESET_BP , & chan -> control );
260+ iowrite8_rep (& chan -> data , value , sizeof (value ));
261+ }
262+
263+ static void quad8_flag_register_reset (struct quad8 * const priv , const size_t id )
264+ {
265+ struct channel_reg __iomem * const chan = priv -> reg -> channel + id ;
266+
267+ iowrite8 (SELECT_RLD | RESET_BT_CT_CPT_S_IDX , & chan -> control );
268+ iowrite8 (SELECT_RLD | RESET_E , & chan -> control );
269+ }
270+
251271static int quad8_count_write (struct counter_device * counter ,
252272 struct counter_count * count , u64 val )
253273{
254274 struct quad8 * const priv = counter_priv (counter );
255275 struct channel_reg __iomem * const chan = priv -> reg -> channel + count -> id ;
256276 unsigned long irqflags ;
257- int i ;
258277
259278 if (val > LS7267_CNTR_MAX )
260279 return - ERANGE ;
261280
262281 spin_lock_irqsave (& priv -> lock , irqflags );
263282
264- iowrite8 (SELECT_RLD | RESET_BP , & chan -> control );
265-
266283 /* Counter can only be set via Preset Register */
267- for (i = 0 ; i < 3 ; i ++ )
268- iowrite8 (val >> (8 * i ), & chan -> data );
269-
284+ quad8_preset_register_set (priv , count -> id , val );
270285 iowrite8 (SELECT_RLD | TRANSFER_PR_TO_CNTR , & chan -> control );
271286
272- iowrite8 ( SELECT_RLD | RESET_BP , & chan -> control );
287+ quad8_flag_register_reset ( priv , count -> id );
273288
274289 /* Set Preset Register back to original value */
275- val = priv -> preset [count -> id ];
276- for (i = 0 ; i < 3 ; i ++ )
277- iowrite8 (val >> (8 * i ), & chan -> data );
278-
279- iowrite8 (SELECT_RLD | RESET_BT_CT_CPT_S_IDX , & chan -> control );
280- iowrite8 (SELECT_RLD | RESET_E , & chan -> control );
290+ quad8_preset_register_set (priv , count -> id , priv -> preset [count -> id ]);
281291
282292 spin_unlock_irqrestore (& priv -> lock , irqflags );
283293
@@ -771,21 +781,6 @@ static int quad8_count_preset_read(struct counter_device *counter,
771781 return 0 ;
772782}
773783
774- static void quad8_preset_register_set (struct quad8 * const priv , const int id ,
775- const unsigned int preset )
776- {
777- struct channel_reg __iomem * const chan = priv -> reg -> channel + id ;
778- int i ;
779-
780- priv -> preset [id ] = preset ;
781-
782- iowrite8 (SELECT_RLD | RESET_BP , & chan -> control );
783-
784- /* Set Preset Register */
785- for (i = 0 ; i < 3 ; i ++ )
786- iowrite8 (preset >> (8 * i ), & chan -> data );
787- }
788-
789784static int quad8_count_preset_write (struct counter_device * counter ,
790785 struct counter_count * count , u64 preset )
791786{
@@ -797,6 +792,7 @@ static int quad8_count_preset_write(struct counter_device *counter,
797792
798793 spin_lock_irqsave (& priv -> lock , irqflags );
799794
795+ priv -> preset [count -> id ] = preset ;
800796 quad8_preset_register_set (priv , count -> id , preset );
801797
802798 spin_unlock_irqrestore (& priv -> lock , irqflags );
@@ -843,6 +839,7 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
843839 switch (u8_get_bits (priv -> cmr [count -> id ], COUNT_MODE )) {
844840 case RANGE_LIMIT :
845841 case MODULO_N :
842+ priv -> preset [count -> id ] = ceiling ;
846843 quad8_preset_register_set (priv , count -> id , ceiling );
847844 spin_unlock_irqrestore (& priv -> lock , irqflags );
848845 return 0 ;
@@ -961,24 +958,28 @@ static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
961958 return 0 ;
962959}
963960
961+ static void quad8_filter_clock_prescaler_set (struct quad8 * const priv , const size_t id ,
962+ const u8 prescaler )
963+ {
964+ struct channel_reg __iomem * const chan = priv -> reg -> channel + id ;
965+
966+ iowrite8 (SELECT_RLD | RESET_BP , & chan -> control );
967+ iowrite8 (prescaler , & chan -> data );
968+ iowrite8 (SELECT_RLD | TRANSFER_PR0_TO_PSC , & chan -> control );
969+ }
970+
964971static int quad8_signal_fck_prescaler_write (struct counter_device * counter ,
965972 struct counter_signal * signal ,
966973 u8 prescaler )
967974{
968975 struct quad8 * const priv = counter_priv (counter );
969976 const size_t channel_id = signal -> id / 2 ;
970- struct channel_reg __iomem * const chan = priv -> reg -> channel + channel_id ;
971977 unsigned long irqflags ;
972978
973979 spin_lock_irqsave (& priv -> lock , irqflags );
974980
975981 priv -> fck_prescaler [channel_id ] = prescaler ;
976-
977- iowrite8 (SELECT_RLD | RESET_BP , & chan -> control );
978-
979- /* Set filter clock factor */
980- iowrite8 (prescaler , & chan -> data );
981- iowrite8 (SELECT_RLD | RESET_BP | TRANSFER_PR0_TO_PSC , & chan -> control );
982+ quad8_filter_clock_prescaler_set (priv , channel_id , prescaler );
982983
983984 spin_unlock_irqrestore (& priv -> lock , irqflags );
984985
@@ -1178,18 +1179,10 @@ static irqreturn_t quad8_irq_handler(int irq, void *private)
11781179static void quad8_init_counter (struct quad8 * const priv , const size_t channel )
11791180{
11801181 struct channel_reg __iomem * const chan = priv -> reg -> channel + channel ;
1181- unsigned long i ;
11821182
1183- iowrite8 (SELECT_RLD | RESET_BP , & chan -> control );
1184- /* Reset filter clock factor */
1185- iowrite8 (0 , & chan -> data );
1186- iowrite8 (SELECT_RLD | RESET_BP | TRANSFER_PR0_TO_PSC , & chan -> control );
1187- iowrite8 (SELECT_RLD | RESET_BP , & chan -> control );
1188- /* Reset Preset Register */
1189- for (i = 0 ; i < 3 ; i ++ )
1190- iowrite8 (0x00 , & chan -> data );
1191- iowrite8 (SELECT_RLD | RESET_BT_CT_CPT_S_IDX , & chan -> control );
1192- iowrite8 (SELECT_RLD | RESET_E , & chan -> control );
1183+ quad8_filter_clock_prescaler_set (priv , channel , 0 );
1184+ quad8_preset_register_set (priv , channel , 0 );
1185+ quad8_flag_register_reset (priv , channel );
11931186
11941187 /* Binary encoding; Normal count; non-quadrature mode */
11951188 priv -> cmr [channel ] = SELECT_CMR | BINARY | u8_encode_bits (NORMAL_COUNT , COUNT_MODE ) |
0 commit comments