lantiq: fix broadcasts and vlans in two iface mode
[oweals/openwrt.git] / target / linux / brcm2708 / patches-4.9 / 0113-i2c-bcm2835-Add-debug-support.patch
1 From 98629f09f3ceb7f2a559b48b4a70028485583f5e Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
3 Date: Tue, 1 Nov 2016 15:15:41 +0100
4 Subject: [PATCH] i2c: bcm2835: Add debug support
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 This adds a debug module parameter to aid in debugging transfer issues
10 by printing info to the kernel log. When enabled, status values are
11 collected in the interrupt routine and msg info in
12 bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid
13 affecting timing. Having printk in the isr can mask issues.
14
15 debug values (additive):
16 1: Print info on error
17 2: Print info on all transfers
18 3: Print messages before transfer is started
19
20 The value can be changed at runtime:
21 /sys/module/i2c_bcm2835/parameters/debug
22
23 Example output, debug=3:
24 [  747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1]
25 [  747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1]
26 [  747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1]
27 [  747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE  [i2c1]
28 [  747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1]
29 [  747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD  [i2c1]
30 [  747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD  [i2c1]
31 [  747.117870] isr: remain=8, status=0x32 : DONE TXD RXD  [i2c1]
32
33 Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
34 ---
35  drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++-
36  1 file changed, 98 insertions(+), 1 deletion(-)
37
38 --- a/drivers/i2c/busses/i2c-bcm2835.c
39 +++ b/drivers/i2c/busses/i2c-bcm2835.c
40 @@ -53,6 +53,18 @@
41  #define BCM2835_I2C_CDIV_MIN   0x0002
42  #define BCM2835_I2C_CDIV_MAX   0xFFFE
43  
44 +static unsigned int debug;
45 +module_param(debug, uint, 0644);
46 +MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer");
47 +
48 +#define BCM2835_DEBUG_MAX      512
49 +struct bcm2835_debug {
50 +       struct i2c_msg *msg;
51 +       int msg_idx;
52 +       size_t remain;
53 +       u32 status;
54 +};
55 +
56  struct bcm2835_i2c_dev {
57         struct device *dev;
58         void __iomem *regs;
59 @@ -66,8 +78,78 @@ struct bcm2835_i2c_dev {
60         u32 msg_err;
61         u8 *msg_buf;
62         size_t msg_buf_remaining;
63 +       struct bcm2835_debug debug[BCM2835_DEBUG_MAX];
64 +       unsigned int debug_num;
65 +       unsigned int debug_num_msgs;
66  };
67  
68 +static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s)
69 +{
70 +       if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX)
71 +               return;
72 +
73 +       i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg;
74 +       i2c_dev->debug[i2c_dev->debug_num].msg_idx =
75 +                               i2c_dev->debug_num_msgs - i2c_dev->num_msgs;
76 +       i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining;
77 +       i2c_dev->debug[i2c_dev->debug_num].status = s;
78 +       i2c_dev->debug_num++;
79 +}
80 +
81 +static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev,
82 +                                      struct bcm2835_debug *d)
83 +{
84 +       u32 s = d->status;
85 +
86 +       pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n",
87 +               d->remain, s,
88 +               s & BCM2835_I2C_S_TA ? "TA " : "",
89 +               s & BCM2835_I2C_S_DONE ? "DONE " : "",
90 +               s & BCM2835_I2C_S_TXW ? "TXW " : "",
91 +               s & BCM2835_I2C_S_RXR ? "RXR " : "",
92 +               s & BCM2835_I2C_S_TXD ? "TXD " : "",
93 +               s & BCM2835_I2C_S_RXD ? "RXD " : "",
94 +               s & BCM2835_I2C_S_TXE ? "TXE " : "",
95 +               s & BCM2835_I2C_S_RXF ? "RXF " : "",
96 +               s & BCM2835_I2C_S_ERR ? "ERR " : "",
97 +               s & BCM2835_I2C_S_CLKT ? "CLKT " : "",
98 +               i2c_dev->adapter.nr);
99 +}
100 +
101 +static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev,
102 +                                   struct i2c_msg *msg, int i, int total,
103 +                                   const char *fname)
104 +{
105 +       pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n",
106 +               fname, i, total,
107 +               msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len,
108 +               msg->flags & I2C_M_TEN ? "TEN" : "",
109 +               msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "",
110 +               msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "",
111 +               msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "",
112 +               msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "",
113 +               msg->flags & I2C_M_NOSTART ? "NOSTART" : "",
114 +               msg->flags & I2C_M_STOP ? "STOP" : "",
115 +               i2c_dev->adapter.nr);
116 +}
117 +
118 +static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev)
119 +{
120 +       struct bcm2835_debug *d;
121 +       unsigned int i;
122 +
123 +       for (i = 0; i < i2c_dev->debug_num; i++) {
124 +               d = &i2c_dev->debug[i];
125 +               if (d->status == ~0)
126 +                       bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx,
127 +                               i2c_dev->debug_num_msgs, "start_transfer");
128 +               else
129 +                       bcm2835_debug_print_status(i2c_dev, d);
130 +       }
131 +       if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX)
132 +               pr_info("BCM2835_DEBUG_MAX reached\n");
133 +}
134 +
135  static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev,
136                                       u32 reg, u32 val)
137  {
138 @@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(s
139         bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
140         bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
141         bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
142 +       bcm2835_debug_add(i2c_dev, ~0);
143  }
144  
145  /*
146 @@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int t
147         u32 val, err;
148  
149         val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
150 +       bcm2835_debug_add(i2c_dev, val);
151  
152         err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
153         if (err) {
154 @@ -251,6 +335,13 @@ static int bcm2835_i2c_xfer(struct i2c_a
155         unsigned long time_left;
156         int i, ret;
157  
158 +       if (debug)
159 +               i2c_dev->debug_num_msgs = num;
160 +
161 +       if (debug > 2)
162 +               for (i = 0; i < num; i++)
163 +                       bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__);
164 +
165         for (i = 0; i < (num - 1); i++)
166                 if (msgs[i].flags & I2C_M_RD) {
167                         dev_warn_once(i2c_dev->dev,
168 @@ -270,6 +361,10 @@ static int bcm2835_i2c_xfer(struct i2c_a
169  
170         time_left = wait_for_completion_timeout(&i2c_dev->completion,
171                                                 adap->timeout);
172 +       if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err)))
173 +               bcm2835_debug_print(i2c_dev);
174 +       i2c_dev->debug_num_msgs = 0;
175 +       i2c_dev->debug_num = 0;
176         if (!time_left) {
177                 bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
178                                    BCM2835_I2C_C_CLEAR);
179 @@ -280,7 +375,9 @@ static int bcm2835_i2c_xfer(struct i2c_a
180         if (!i2c_dev->msg_err)
181                 return num;
182  
183 -       dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
184 +       if (debug)
185 +               dev_err(i2c_dev->dev, "i2c transfer failed: %x\n",
186 +                       i2c_dev->msg_err);
187  
188         if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
189                 return -EREMOTEIO;