xref: /linux/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c (revision e5c86679d5e864947a52fb31e45a425dea3e7fa9)
1 /*
2  * aQuantia Corporation Network Driver
3  * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  */
9 
10 /* File aq_hw_utils.c: Definitions of helper functions used across
11  * hardware layer.
12  */
13 
14 #include "aq_hw_utils.h"
15 #include "aq_hw.h"
16 
17 void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
18 			 u32 shift, u32 val)
19 {
20 	if (msk ^ ~0) {
21 		u32 reg_old, reg_new;
22 
23 		reg_old = aq_hw_read_reg(aq_hw, addr);
24 		reg_new = (reg_old & (~msk)) | (val << shift);
25 
26 		if (reg_old != reg_new)
27 			aq_hw_write_reg(aq_hw, addr, reg_new);
28 	} else {
29 		aq_hw_write_reg(aq_hw, addr, val);
30 	}
31 }
32 
33 u32 aq_hw_read_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, u32 shift)
34 {
35 	return ((aq_hw_read_reg(aq_hw, addr) & msk) >> shift);
36 }
37 
38 u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg)
39 {
40 	u32 value = readl(hw->mmio + reg);
41 
42 	if ((~0U) == value && (~0U) == readl(hw->mmio + hw->not_ff_addr))
43 		aq_utils_obj_set(&hw->header.flags, AQ_HW_FLAG_ERR_UNPLUG);
44 
45 	return value;
46 }
47 
48 void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value)
49 {
50 	writel(value, hw->mmio + reg);
51 }
52 
53 int aq_hw_err_from_flags(struct aq_hw_s *hw)
54 {
55 	int err = 0;
56 
57 	if (aq_utils_obj_test(&hw->header.flags, AQ_HW_FLAG_ERR_UNPLUG)) {
58 		err = -ENXIO;
59 		goto err_exit;
60 	}
61 	if (aq_utils_obj_test(&hw->header.flags, AQ_HW_FLAG_ERR_HW)) {
62 		err = -EIO;
63 		goto err_exit;
64 	}
65 
66 err_exit:
67 	return err;
68 }
69