diff options
author | Kamal Dasu <kdasu.kdev@gmail.com> | 2015-06-09 15:36:20 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2015-06-10 09:02:57 -0400 |
commit | dd1aa2524bc55345ede0b13853c54e1b0be22b9f (patch) | |
tree | cced9b59b0f881ce8a46eb8d05a018f2350ba121 | |
parent | 5e3cfc6c4e37ec7040fa235f42586b3312c0ebf2 (diff) |
i2c: brcmstb: Add Broadcom settop SoC i2c controller driver
Adding support for i2c controller driver for Broadcom settop
SoCs.
Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
[wsa: removed superfluous owner in platform_driver]
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r-- | Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt | 28 | ||||
-rw-r--r-- | drivers/i2c/busses/Kconfig | 10 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-brcmstb.c | 694 |
4 files changed, 733 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt b/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt new file mode 100644 index 000000000000..d6f724efdcf2 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt | |||
@@ -0,0 +1,28 @@ | |||
1 | Broadcom stb bsc iic master controller | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible: should be "brcm,brcmstb-i2c" | ||
6 | - clock-frequency: 32-bit decimal value of iic master clock freqency in Hz | ||
7 | valid values are 375000, 390000, 187500, 200000 | ||
8 | 93750, 97500, 46875 and 50000 | ||
9 | - reg: specifies the base physical address and size of the registers | ||
10 | |||
11 | Optional properties : | ||
12 | |||
13 | - interrupt-parent: specifies the phandle to the parent interrupt controller | ||
14 | this one is cascaded from | ||
15 | - interrupts: specifies the interrupt number, the irq line to be used | ||
16 | - interrupt-names: Interrupt name string | ||
17 | |||
18 | Example: | ||
19 | |||
20 | bsca: i2c@f0406200 { | ||
21 | clock-frequency = <390000>; | ||
22 | compatible = "brcm,brcmstb-i2c"; | ||
23 | interrupt-parent = <&irq0_intc>; | ||
24 | reg = <0xf0406200 0x58>; | ||
25 | interrupts = <0x18>; | ||
26 | interrupt-names = "upg_bsca"; | ||
27 | }; | ||
28 | |||
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 8a639dce5173..b8c3d6b53861 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -392,6 +392,16 @@ config I2C_BCM_KONA | |||
392 | 392 | ||
393 | If you do not need KONA I2C interface, say N. | 393 | If you do not need KONA I2C interface, say N. |
394 | 394 | ||
395 | config I2C_BRCMSTB | ||
396 | tristate "BRCM Settop I2C controller" | ||
397 | depends on ARCH_BRCMSTB || COMPILE_TEST | ||
398 | default y | ||
399 | help | ||
400 | If you say yes to this option, support will be included for the | ||
401 | I2C interface on the Broadcom Settop SoCs. | ||
402 | |||
403 | If you do not need I2C interface, say N. | ||
404 | |||
395 | config I2C_BLACKFIN_TWI | 405 | config I2C_BLACKFIN_TWI |
396 | tristate "Blackfin TWI I2C support" | 406 | tristate "Blackfin TWI I2C support" |
397 | depends on BLACKFIN | 407 | depends on BLACKFIN |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 65995423c680..e5f537c80da0 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -106,6 +106,7 @@ obj-$(CONFIG_I2C_VIPERBOARD) += i2c-viperboard.o | |||
106 | # Other I2C/SMBus bus drivers | 106 | # Other I2C/SMBus bus drivers |
107 | obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o | 107 | obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o |
108 | obj-$(CONFIG_I2C_BCM_KONA) += i2c-bcm-kona.o | 108 | obj-$(CONFIG_I2C_BCM_KONA) += i2c-bcm-kona.o |
109 | obj-$(CONFIG_I2C_BRCMSTB) += i2c-brcmstb.o | ||
109 | obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o | 110 | obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o |
110 | obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o | 111 | obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o |
111 | obj-$(CONFIG_I2C_OPAL) += i2c-opal.o | 112 | obj-$(CONFIG_I2C_OPAL) += i2c-opal.o |
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c new file mode 100644 index 000000000000..8e9637eea512 --- /dev/null +++ b/drivers/i2c/busses/i2c-brcmstb.c | |||
@@ -0,0 +1,694 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/version.h> | ||
26 | |||
27 | #define N_DATA_REGS 8 | ||
28 | #define N_DATA_BYTES (N_DATA_REGS * 4) | ||
29 | |||
30 | /* BSC count register field definitions */ | ||
31 | #define BSC_CNT_REG1_MASK 0x0000003f | ||
32 | #define BSC_CNT_REG1_SHIFT 0 | ||
33 | #define BSC_CNT_REG2_MASK 0x00000fc0 | ||
34 | #define BSC_CNT_REG2_SHIFT 6 | ||
35 | |||
36 | /* BSC CTL register field definitions */ | ||
37 | #define BSC_CTL_REG_DTF_MASK 0x00000003 | ||
38 | #define BSC_CTL_REG_SCL_SEL_MASK 0x00000030 | ||
39 | #define BSC_CTL_REG_SCL_SEL_SHIFT 4 | ||
40 | #define BSC_CTL_REG_INT_EN_MASK 0x00000040 | ||
41 | #define BSC_CTL_REG_INT_EN_SHIFT 6 | ||
42 | #define BSC_CTL_REG_DIV_CLK_MASK 0x00000080 | ||
43 | |||
44 | /* BSC_IIC_ENABLE r/w enable and interrupt field defintions */ | ||
45 | #define BSC_IIC_EN_RESTART_MASK 0x00000040 | ||
46 | #define BSC_IIC_EN_NOSTART_MASK 0x00000020 | ||
47 | #define BSC_IIC_EN_NOSTOP_MASK 0x00000010 | ||
48 | #define BSC_IIC_EN_NOACK_MASK 0x00000004 | ||
49 | #define BSC_IIC_EN_INTRP_MASK 0x00000002 | ||
50 | #define BSC_IIC_EN_ENABLE_MASK 0x00000001 | ||
51 | |||
52 | /* BSC_CTLHI control register field definitions */ | ||
53 | #define BSC_CTLHI_REG_INPUT_SWITCHING_LEVEL_MASK 0x00000080 | ||
54 | #define BSC_CTLHI_REG_DATAREG_SIZE_MASK 0x00000040 | ||
55 | #define BSC_CTLHI_REG_IGNORE_ACK_MASK 0x00000002 | ||
56 | #define BSC_CTLHI_REG_WAIT_DIS_MASK 0x00000001 | ||
57 | |||
58 | #define I2C_TIMEOUT 100 /* msecs */ | ||
59 | |||
60 | /* Condition mask used for non combined transfer */ | ||
61 | #define COND_RESTART BSC_IIC_EN_RESTART_MASK | ||
62 | #define COND_NOSTART BSC_IIC_EN_NOSTART_MASK | ||
63 | #define COND_NOSTOP BSC_IIC_EN_NOSTOP_MASK | ||
64 | #define COND_START_STOP (COND_RESTART | COND_NOSTART | COND_NOSTOP) | ||
65 | |||
66 | /* BSC data transfer direction */ | ||
67 | #define DTF_WR_MASK 0x00000000 | ||
68 | #define DTF_RD_MASK 0x00000001 | ||
69 | /* BSC data transfer direction combined format */ | ||
70 | #define DTF_RD_WR_MASK 0x00000002 | ||
71 | #define DTF_WR_RD_MASK 0x00000003 | ||
72 | |||
73 | #define INT_ENABLE true | ||
74 | #define INT_DISABLE false | ||
75 | |||
76 | /* BSC block register map structure to cache fields to be written */ | ||
77 | struct bsc_regs { | ||
78 | u32 chip_address; /* slave address */ | ||
79 | u32 data_in[N_DATA_REGS]; /* tx data buffer*/ | ||
80 | u32 cnt_reg; /* rx/tx data length */ | ||
81 | u32 ctl_reg; /* control register */ | ||
82 | u32 iic_enable; /* xfer enable and status */ | ||
83 | u32 data_out[N_DATA_REGS]; /* rx data buffer */ | ||
84 | u32 ctlhi_reg; /* more control fields */ | ||
85 | u32 scl_param; /* reserved */ | ||
86 | }; | ||
87 | |||
88 | struct bsc_clk_param { | ||
89 | u32 hz; | ||
90 | u32 scl_mask; | ||
91 | u32 div_mask; | ||
92 | }; | ||
93 | |||
94 | enum bsc_xfer_cmd { | ||
95 | CMD_WR, | ||
96 | CMD_RD, | ||
97 | CMD_WR_NOACK, | ||
98 | CMD_RD_NOACK, | ||
99 | }; | ||
100 | |||
101 | static char const *cmd_string[] = { | ||
102 | [CMD_WR] = "WR", | ||
103 | [CMD_RD] = "RD", | ||
104 | [CMD_WR_NOACK] = "WR NOACK", | ||
105 | [CMD_RD_NOACK] = "RD NOACK", | ||
106 | }; | ||
107 | |||
108 | enum bus_speeds { | ||
109 | SPD_375K, | ||
110 | SPD_390K, | ||
111 | SPD_187K, | ||
112 | SPD_200K, | ||
113 | SPD_93K, | ||
114 | SPD_97K, | ||
115 | SPD_46K, | ||
116 | SPD_50K | ||
117 | }; | ||
118 | |||
119 | static const struct bsc_clk_param bsc_clk[] = { | ||
120 | [SPD_375K] = { | ||
121 | .hz = 375000, | ||
122 | .scl_mask = SPD_375K << BSC_CTL_REG_SCL_SEL_SHIFT, | ||
123 | .div_mask = 0 | ||
124 | }, | ||
125 | [SPD_390K] = { | ||
126 | .hz = 390000, | ||
127 | .scl_mask = SPD_390K << BSC_CTL_REG_SCL_SEL_SHIFT, | ||
128 | .div_mask = 0 | ||
129 | }, | ||
130 | [SPD_187K] = { | ||
131 | .hz = 187500, | ||
132 | .scl_mask = SPD_187K << BSC_CTL_REG_SCL_SEL_SHIFT, | ||
133 | .div_mask = 0 | ||
134 | }, | ||
135 | [SPD_200K] = { | ||
136 | .hz = 200000, | ||
137 | .scl_mask = SPD_200K << BSC_CTL_REG_SCL_SEL_SHIFT, | ||
138 | .div_mask = 0 | ||
139 | }, | ||
140 | [SPD_93K] = { | ||
141 | .hz = 93750, | ||
142 | .scl_mask = SPD_375K << BSC_CTL_REG_SCL_SEL_SHIFT, | ||
143 | .div_mask = BSC_CTL_REG_DIV_CLK_MASK | ||
144 | }, | ||
145 | [SPD_97K] = { | ||
146 | .hz = 97500, | ||
147 | .scl_mask = SPD_390K << BSC_CTL_REG_SCL_SEL_SHIFT, | ||
148 | .div_mask = BSC_CTL_REG_DIV_CLK_MASK | ||
149 | }, | ||
150 | [SPD_46K] = { | ||
151 | .hz = 46875, | ||
152 | .scl_mask = SPD_187K << BSC_CTL_REG_SCL_SEL_SHIFT, | ||
153 | .div_mask = BSC_CTL_REG_DIV_CLK_MASK | ||
154 | }, | ||
155 | [SPD_50K] = { | ||
156 | .hz = 50000, | ||
157 | .scl_mask = SPD_200K << BSC_CTL_REG_SCL_SEL_SHIFT, | ||
158 | .div_mask = BSC_CTL_REG_DIV_CLK_MASK | ||
159 | } | ||
160 | }; | ||
161 | |||
162 | struct brcmstb_i2c_dev { | ||
163 | struct device *device; | ||
164 | void __iomem *base; | ||
165 | void __iomem *irq_base; | ||
166 | int irq; | ||
167 | struct bsc_regs *bsc_regmap; | ||
168 | struct i2c_adapter adapter; | ||
169 | struct completion done; | ||
170 | bool is_suspended; | ||
171 | u32 clk_freq_hz; | ||
172 | }; | ||
173 | |||
174 | /* register accessors for both be and le cpu arch */ | ||
175 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
176 | #define __bsc_readl(_reg) ioread32be(_reg) | ||
177 | #define __bsc_writel(_val, _reg) iowrite32be(_val, _reg) | ||
178 | #else | ||
179 | #define __bsc_readl(_reg) ioread32(_reg) | ||
180 | #define __bsc_writel(_val, _reg) iowrite32(_val, _reg) | ||
181 | #endif | ||
182 | |||
183 | #define bsc_readl(_dev, _reg) \ | ||
184 | __bsc_readl(_dev->base + offsetof(struct bsc_regs, _reg)) | ||
185 | |||
186 | #define bsc_writel(_dev, _val, _reg) \ | ||
187 | __bsc_writel(_val, _dev->base + offsetof(struct bsc_regs, _reg)) | ||
188 | |||
189 | static void brcmstb_i2c_enable_disable_irq(struct brcmstb_i2c_dev *dev, | ||
190 | bool int_en) | ||
191 | { | ||
192 | |||
193 | if (int_en) | ||
194 | /* Enable BSC CTL interrupt line */ | ||
195 | dev->bsc_regmap->ctl_reg |= BSC_CTL_REG_INT_EN_MASK; | ||
196 | else | ||
197 | /* Disable BSC CTL interrupt line */ | ||
198 | dev->bsc_regmap->ctl_reg &= ~BSC_CTL_REG_INT_EN_MASK; | ||
199 | |||
200 | barrier(); | ||
201 | bsc_writel(dev, dev->bsc_regmap->ctl_reg, ctl_reg); | ||
202 | } | ||
203 | |||
204 | static irqreturn_t brcmstb_i2c_isr(int irq, void *devid) | ||
205 | { | ||
206 | struct brcmstb_i2c_dev *dev = devid; | ||
207 | u32 status_bsc_ctl = bsc_readl(dev, ctl_reg); | ||
208 | u32 status_iic_intrp = bsc_readl(dev, iic_enable); | ||
209 | |||
210 | dev_dbg(dev->device, "isr CTL_REG %x IIC_EN %x\n", | ||
211 | status_bsc_ctl, status_iic_intrp); | ||
212 | |||
213 | if (!(status_bsc_ctl & BSC_CTL_REG_INT_EN_MASK)) | ||
214 | return IRQ_NONE; | ||
215 | |||
216 | brcmstb_i2c_enable_disable_irq(dev, INT_DISABLE); | ||
217 | complete_all(&dev->done); | ||
218 | |||
219 | dev_dbg(dev->device, "isr handled"); | ||
220 | return IRQ_HANDLED; | ||
221 | } | ||
222 | |||
223 | /* Wait for device to be ready */ | ||
224 | static int brcmstb_i2c_wait_if_busy(struct brcmstb_i2c_dev *dev) | ||
225 | { | ||
226 | unsigned long timeout = jiffies + msecs_to_jiffies(I2C_TIMEOUT); | ||
227 | |||
228 | while ((bsc_readl(dev, iic_enable) & BSC_IIC_EN_INTRP_MASK)) { | ||
229 | if (time_after(jiffies, timeout)) | ||
230 | return -ETIMEDOUT; | ||
231 | cpu_relax(); | ||
232 | } | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | /* i2c xfer completion function, handles both irq and polling mode */ | ||
237 | static int brcmstb_i2c_wait_for_completion(struct brcmstb_i2c_dev *dev) | ||
238 | { | ||
239 | int ret = 0; | ||
240 | unsigned long timeout = msecs_to_jiffies(I2C_TIMEOUT); | ||
241 | |||
242 | if (dev->irq >= 0) { | ||
243 | if (!wait_for_completion_timeout(&dev->done, timeout)) | ||
244 | ret = -ETIMEDOUT; | ||
245 | } else { | ||
246 | /* we are in polling mode */ | ||
247 | u32 bsc_intrp; | ||
248 | unsigned long time_left = jiffies + timeout; | ||
249 | |||
250 | do { | ||
251 | bsc_intrp = bsc_readl(dev, iic_enable) & | ||
252 | BSC_IIC_EN_INTRP_MASK; | ||
253 | if (time_after(jiffies, time_left)) { | ||
254 | ret = -ETIMEDOUT; | ||
255 | break; | ||
256 | } | ||
257 | cpu_relax(); | ||
258 | } while (!bsc_intrp); | ||
259 | } | ||
260 | |||
261 | if (dev->irq < 0 || ret == -ETIMEDOUT) | ||
262 | brcmstb_i2c_enable_disable_irq(dev, INT_DISABLE); | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | /* Set xfer START/STOP conditions for subsequent transfer */ | ||
268 | static void brcmstb_set_i2c_start_stop(struct brcmstb_i2c_dev *dev, | ||
269 | u32 cond_flag) | ||
270 | { | ||
271 | u32 regval = dev->bsc_regmap->iic_enable; | ||
272 | |||
273 | dev->bsc_regmap->iic_enable = (regval & ~COND_START_STOP) | cond_flag; | ||
274 | } | ||
275 | |||
276 | /* Send I2C request check completion */ | ||
277 | static int brcmstb_send_i2c_cmd(struct brcmstb_i2c_dev *dev, | ||
278 | enum bsc_xfer_cmd cmd) | ||
279 | { | ||
280 | int rc = 0; | ||
281 | struct bsc_regs *pi2creg = dev->bsc_regmap; | ||
282 | |||
283 | /* Make sure the hardware is ready */ | ||
284 | rc = brcmstb_i2c_wait_if_busy(dev); | ||
285 | if (rc < 0) | ||
286 | return rc; | ||
287 | |||
288 | /* only if we are in interrupt mode */ | ||
289 | if (dev->irq >= 0) | ||
290 | reinit_completion(&dev->done); | ||
291 | |||
292 | /* enable BSC CTL interrupt line */ | ||
293 | brcmstb_i2c_enable_disable_irq(dev, INT_ENABLE); | ||
294 | |||
295 | /* initiate transfer by setting iic_enable */ | ||
296 | pi2creg->iic_enable |= BSC_IIC_EN_ENABLE_MASK; | ||
297 | bsc_writel(dev, pi2creg->iic_enable, iic_enable); | ||
298 | |||
299 | /* Wait for transaction to finish or timeout */ | ||
300 | rc = brcmstb_i2c_wait_for_completion(dev); | ||
301 | if (rc) { | ||
302 | dev_dbg(dev->device, "intr timeout for cmd %s\n", | ||
303 | cmd_string[cmd]); | ||
304 | goto cmd_out; | ||
305 | } | ||
306 | |||
307 | if ((CMD_RD || CMD_WR) && | ||
308 | bsc_readl(dev, iic_enable) & BSC_IIC_EN_NOACK_MASK) { | ||
309 | rc = -EREMOTEIO; | ||
310 | dev_dbg(dev->device, "controller received NOACK intr for %s\n", | ||
311 | cmd_string[cmd]); | ||
312 | } | ||
313 | |||
314 | cmd_out: | ||
315 | bsc_writel(dev, 0, cnt_reg); | ||
316 | bsc_writel(dev, 0, iic_enable); | ||
317 | |||
318 | return rc; | ||
319 | } | ||
320 | |||
321 | /* Actual data transfer through the BSC master */ | ||
322 | static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev, | ||
323 | u8 *buf, unsigned int len, | ||
324 | struct i2c_msg *pmsg) | ||
325 | { | ||
326 | int cnt, byte, rc; | ||
327 | enum bsc_xfer_cmd cmd; | ||
328 | u32 ctl_reg; | ||
329 | struct bsc_regs *pi2creg = dev->bsc_regmap; | ||
330 | int no_ack = pmsg->flags & I2C_M_IGNORE_NAK; | ||
331 | |||
332 | /* see if the transaction needs to check NACK conditions */ | ||
333 | if (no_ack || len <= N_DATA_BYTES) { | ||
334 | cmd = (pmsg->flags & I2C_M_RD) ? CMD_RD_NOACK | ||
335 | : CMD_WR_NOACK; | ||
336 | pi2creg->ctlhi_reg |= BSC_CTLHI_REG_IGNORE_ACK_MASK; | ||
337 | } else { | ||
338 | cmd = (pmsg->flags & I2C_M_RD) ? CMD_RD : CMD_WR; | ||
339 | pi2creg->ctlhi_reg &= ~BSC_CTLHI_REG_IGNORE_ACK_MASK; | ||
340 | } | ||
341 | bsc_writel(dev, pi2creg->ctlhi_reg, ctlhi_reg); | ||
342 | |||
343 | /* set data transfer direction */ | ||
344 | ctl_reg = pi2creg->ctl_reg & ~BSC_CTL_REG_DTF_MASK; | ||
345 | if (cmd == CMD_WR || cmd == CMD_WR_NOACK) | ||
346 | pi2creg->ctl_reg = ctl_reg | DTF_WR_MASK; | ||
347 | else | ||
348 | pi2creg->ctl_reg = ctl_reg | DTF_RD_MASK; | ||
349 | |||
350 | /* set the read/write length */ | ||
351 | bsc_writel(dev, BSC_CNT_REG1_MASK & (len << BSC_CNT_REG1_SHIFT), | ||
352 | cnt_reg); | ||
353 | |||
354 | /* Write data into data_in register */ | ||
355 | if (cmd == CMD_WR || cmd == CMD_WR_NOACK) { | ||
356 | for (cnt = 0; cnt < len; cnt += 4) { | ||
357 | u32 word = 0; | ||
358 | |||
359 | for (byte = 0; byte < 4; byte++) { | ||
360 | word >>= 8; | ||
361 | if ((cnt + byte) < len) | ||
362 | word |= buf[cnt + byte] << 24; | ||
363 | } | ||
364 | bsc_writel(dev, word, data_in[cnt >> 2]); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | /* Initiate xfer, the function will return on completion */ | ||
369 | rc = brcmstb_send_i2c_cmd(dev, cmd); | ||
370 | |||
371 | if (rc != 0) { | ||
372 | dev_dbg(dev->device, "%s failure", cmd_string[cmd]); | ||
373 | return rc; | ||
374 | } | ||
375 | |||
376 | if (cmd == CMD_RD || cmd == CMD_RD_NOACK) { | ||
377 | for (cnt = 0; cnt < len; cnt += 4) { | ||
378 | u32 data = bsc_readl(dev, data_out[cnt >> 2]); | ||
379 | |||
380 | for (byte = 0; byte < 4 && | ||
381 | (byte + cnt) < len; byte++) { | ||
382 | buf[cnt + byte] = data & 0xff; | ||
383 | data >>= 8; | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | /* Write a single byte of data to the i2c bus */ | ||
392 | static int brcmstb_i2c_write_data_byte(struct brcmstb_i2c_dev *dev, | ||
393 | u8 *buf, unsigned int nak_expected) | ||
394 | { | ||
395 | enum bsc_xfer_cmd cmd = nak_expected ? CMD_WR : CMD_WR_NOACK; | ||
396 | |||
397 | bsc_writel(dev, 1, cnt_reg); | ||
398 | bsc_writel(dev, *buf, data_in); | ||
399 | |||
400 | return brcmstb_send_i2c_cmd(dev, cmd); | ||
401 | } | ||
402 | |||
403 | /* Send i2c address */ | ||
404 | static int brcmstb_i2c_do_addr(struct brcmstb_i2c_dev *dev, | ||
405 | struct i2c_msg *msg) | ||
406 | { | ||
407 | unsigned char addr; | ||
408 | |||
409 | if (msg->flags & I2C_M_TEN) { | ||
410 | /* First byte is 11110XX0 where XX is upper 2 bits */ | ||
411 | addr = 0xF0 | ((msg->addr & 0x300) >> 7); | ||
412 | bsc_writel(dev, addr, chip_address); | ||
413 | |||
414 | /* Second byte is the remaining 8 bits */ | ||
415 | addr = msg->addr & 0xFF; | ||
416 | if (brcmstb_i2c_write_data_byte(dev, &addr, 0) < 0) | ||
417 | return -EREMOTEIO; | ||
418 | |||
419 | if (msg->flags & I2C_M_RD) { | ||
420 | /* For read, send restart without stop condition */ | ||
421 | brcmstb_set_i2c_start_stop(dev, COND_RESTART | ||
422 | | COND_NOSTOP); | ||
423 | /* Then re-send the first byte with the read bit set */ | ||
424 | addr = 0xF0 | ((msg->addr & 0x300) >> 7) | 0x01; | ||
425 | if (brcmstb_i2c_write_data_byte(dev, &addr, 0) < 0) | ||
426 | return -EREMOTEIO; | ||
427 | |||
428 | } | ||
429 | } else { | ||
430 | addr = msg->addr << 1; | ||
431 | if (msg->flags & I2C_M_RD) | ||
432 | addr |= 1; | ||
433 | |||
434 | bsc_writel(dev, addr, chip_address); | ||
435 | } | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | /* Master transfer function */ | ||
441 | static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, | ||
442 | struct i2c_msg msgs[], int num) | ||
443 | { | ||
444 | struct brcmstb_i2c_dev *dev = i2c_get_adapdata(adapter); | ||
445 | struct i2c_msg *pmsg; | ||
446 | int rc = 0; | ||
447 | int i; | ||
448 | int bytes_to_xfer; | ||
449 | u8 *tmp_buf; | ||
450 | int len = 0; | ||
451 | |||
452 | if (dev->is_suspended) | ||
453 | return -EBUSY; | ||
454 | |||
455 | /* Loop through all messages */ | ||
456 | for (i = 0; i < num; i++) { | ||
457 | pmsg = &msgs[i]; | ||
458 | len = pmsg->len; | ||
459 | tmp_buf = pmsg->buf; | ||
460 | |||
461 | dev_dbg(dev->device, | ||
462 | "msg# %d/%d flg %x buf %x len %d\n", i, | ||
463 | num - 1, pmsg->flags, | ||
464 | pmsg->buf ? pmsg->buf[0] : '0', pmsg->len); | ||
465 | |||
466 | if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART)) | ||
467 | brcmstb_set_i2c_start_stop(dev, ~(COND_START_STOP)); | ||
468 | else | ||
469 | brcmstb_set_i2c_start_stop(dev, | ||
470 | COND_RESTART | COND_NOSTOP); | ||
471 | |||
472 | /* Send slave address */ | ||
473 | if (!(pmsg->flags & I2C_M_NOSTART)) { | ||
474 | rc = brcmstb_i2c_do_addr(dev, pmsg); | ||
475 | if (rc < 0) { | ||
476 | dev_dbg(dev->device, | ||
477 | "NACK for addr %2.2x msg#%d rc = %d\n", | ||
478 | pmsg->addr, i, rc); | ||
479 | goto out; | ||
480 | } | ||
481 | } | ||
482 | |||
483 | /* Perform data transfer */ | ||
484 | while (len) { | ||
485 | bytes_to_xfer = min(len, N_DATA_BYTES); | ||
486 | |||
487 | if (len <= N_DATA_BYTES && i == (num - 1)) | ||
488 | brcmstb_set_i2c_start_stop(dev, | ||
489 | ~(COND_START_STOP)); | ||
490 | |||
491 | rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf, | ||
492 | bytes_to_xfer, pmsg); | ||
493 | if (rc < 0) | ||
494 | goto out; | ||
495 | |||
496 | len -= bytes_to_xfer; | ||
497 | tmp_buf += bytes_to_xfer; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | rc = num; | ||
502 | out: | ||
503 | return rc; | ||
504 | |||
505 | } | ||
506 | |||
507 | static u32 brcmstb_i2c_functionality(struct i2c_adapter *adap) | ||
508 | { | ||
509 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | ||
510 | | I2C_FUNC_NOSTART | I2C_FUNC_PROTOCOL_MANGLING; | ||
511 | } | ||
512 | |||
513 | static const struct i2c_algorithm brcmstb_i2c_algo = { | ||
514 | .master_xfer = brcmstb_i2c_xfer, | ||
515 | .functionality = brcmstb_i2c_functionality, | ||
516 | }; | ||
517 | |||
518 | static void brcmstb_i2c_set_bus_speed(struct brcmstb_i2c_dev *dev) | ||
519 | { | ||
520 | int i = 0, num_speeds = ARRAY_SIZE(bsc_clk); | ||
521 | u32 clk_freq_hz = dev->clk_freq_hz; | ||
522 | |||
523 | for (i = 0; i < num_speeds; i++) { | ||
524 | if (bsc_clk[i].hz == clk_freq_hz) { | ||
525 | dev->bsc_regmap->ctl_reg &= ~(BSC_CTL_REG_SCL_SEL_MASK | ||
526 | | BSC_CTL_REG_DIV_CLK_MASK); | ||
527 | dev->bsc_regmap->ctl_reg |= (bsc_clk[i].scl_mask | | ||
528 | bsc_clk[i].div_mask); | ||
529 | bsc_writel(dev, dev->bsc_regmap->ctl_reg, ctl_reg); | ||
530 | break; | ||
531 | } | ||
532 | } | ||
533 | |||
534 | /* in case we did not get find a valid speed */ | ||
535 | if (i == num_speeds) { | ||
536 | i = (bsc_readl(dev, ctl_reg) & BSC_CTL_REG_SCL_SEL_MASK) >> | ||
537 | BSC_CTL_REG_SCL_SEL_SHIFT; | ||
538 | dev_warn(dev->device, "leaving current clock-frequency @ %dHz\n", | ||
539 | bsc_clk[i].hz); | ||
540 | } | ||
541 | } | ||
542 | |||
543 | static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev) | ||
544 | { | ||
545 | /* 4 byte data register */ | ||
546 | dev->bsc_regmap->ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK; | ||
547 | bsc_writel(dev, dev->bsc_regmap->ctlhi_reg, ctlhi_reg); | ||
548 | /* set bus speed */ | ||
549 | brcmstb_i2c_set_bus_speed(dev); | ||
550 | } | ||
551 | |||
552 | static int brcmstb_i2c_probe(struct platform_device *pdev) | ||
553 | { | ||
554 | int rc = 0; | ||
555 | struct brcmstb_i2c_dev *dev; | ||
556 | struct i2c_adapter *adap; | ||
557 | struct resource *iomem; | ||
558 | const char *int_name; | ||
559 | |||
560 | /* Allocate memory for private data structure */ | ||
561 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); | ||
562 | if (!dev) | ||
563 | return -ENOMEM; | ||
564 | |||
565 | dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(struct bsc_regs *), | ||
566 | GFP_KERNEL); | ||
567 | if (!dev->bsc_regmap) | ||
568 | return -ENOMEM; | ||
569 | |||
570 | platform_set_drvdata(pdev, dev); | ||
571 | dev->device = &pdev->dev; | ||
572 | init_completion(&dev->done); | ||
573 | |||
574 | /* Map hardware registers */ | ||
575 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
576 | dev->base = devm_ioremap_resource(dev->device, iomem); | ||
577 | if (IS_ERR(dev->base)) { | ||
578 | rc = -ENOMEM; | ||
579 | goto probe_errorout; | ||
580 | } | ||
581 | |||
582 | rc = of_property_read_string(dev->device->of_node, "interrupt-names", | ||
583 | &int_name); | ||
584 | if (rc < 0) | ||
585 | int_name = NULL; | ||
586 | |||
587 | /* Get the interrupt number */ | ||
588 | dev->irq = platform_get_irq(pdev, 0); | ||
589 | |||
590 | /* disable the bsc interrupt line */ | ||
591 | brcmstb_i2c_enable_disable_irq(dev, INT_DISABLE); | ||
592 | |||
593 | /* register the ISR handler */ | ||
594 | rc = devm_request_irq(&pdev->dev, dev->irq, brcmstb_i2c_isr, | ||
595 | IRQF_SHARED, | ||
596 | int_name ? int_name : pdev->name, | ||
597 | dev); | ||
598 | |||
599 | if (rc) { | ||
600 | dev_dbg(dev->device, "falling back to polling mode"); | ||
601 | dev->irq = -1; | ||
602 | } | ||
603 | |||
604 | if (of_property_read_u32(dev->device->of_node, | ||
605 | "clock-frequency", &dev->clk_freq_hz)) { | ||
606 | dev_warn(dev->device, "setting clock-frequency@%dHz\n", | ||
607 | bsc_clk[0].hz); | ||
608 | dev->clk_freq_hz = bsc_clk[0].hz; | ||
609 | } | ||
610 | |||
611 | brcmstb_i2c_set_bsc_reg_defaults(dev); | ||
612 | |||
613 | /* Add the i2c adapter */ | ||
614 | adap = &dev->adapter; | ||
615 | i2c_set_adapdata(adap, dev); | ||
616 | adap->owner = THIS_MODULE; | ||
617 | strlcpy(adap->name, "Broadcom STB : ", sizeof(adap->name)); | ||
618 | if (int_name) | ||
619 | strlcat(adap->name, int_name, sizeof(adap->name)); | ||
620 | adap->algo = &brcmstb_i2c_algo; | ||
621 | adap->dev.parent = &pdev->dev; | ||
622 | adap->dev.of_node = pdev->dev.of_node; | ||
623 | rc = i2c_add_adapter(adap); | ||
624 | if (rc) { | ||
625 | dev_err(dev->device, "failed to add adapter\n"); | ||
626 | goto probe_errorout; | ||
627 | } | ||
628 | |||
629 | dev_info(dev->device, "%s@%dhz registered in %s mode\n", | ||
630 | int_name ? int_name : " ", dev->clk_freq_hz, | ||
631 | (dev->irq >= 0) ? "interrupt" : "polling"); | ||
632 | |||
633 | return 0; | ||
634 | |||
635 | probe_errorout: | ||
636 | return rc; | ||
637 | } | ||
638 | |||
639 | static int brcmstb_i2c_remove(struct platform_device *pdev) | ||
640 | { | ||
641 | struct brcmstb_i2c_dev *dev = platform_get_drvdata(pdev); | ||
642 | |||
643 | i2c_del_adapter(&dev->adapter); | ||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | #ifdef CONFIG_PM_SLEEP | ||
648 | static int brcmstb_i2c_suspend(struct device *dev) | ||
649 | { | ||
650 | struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev); | ||
651 | |||
652 | i2c_lock_adapter(&i2c_dev->adapter); | ||
653 | i2c_dev->is_suspended = true; | ||
654 | i2c_unlock_adapter(&i2c_dev->adapter); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static int brcmstb_i2c_resume(struct device *dev) | ||
660 | { | ||
661 | struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev); | ||
662 | |||
663 | i2c_lock_adapter(&i2c_dev->adapter); | ||
664 | brcmstb_i2c_set_bsc_reg_defaults(i2c_dev); | ||
665 | i2c_dev->is_suspended = false; | ||
666 | i2c_unlock_adapter(&i2c_dev->adapter); | ||
667 | |||
668 | return 0; | ||
669 | } | ||
670 | #endif | ||
671 | |||
672 | static SIMPLE_DEV_PM_OPS(brcmstb_i2c_pm, brcmstb_i2c_suspend, | ||
673 | brcmstb_i2c_resume); | ||
674 | |||
675 | static const struct of_device_id brcmstb_i2c_of_match[] = { | ||
676 | {.compatible = "brcm,brcmstb-i2c"}, | ||
677 | {}, | ||
678 | }; | ||
679 | MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match); | ||
680 | |||
681 | static struct platform_driver brcmstb_i2c_driver = { | ||
682 | .driver = { | ||
683 | .name = "brcmstb-i2c", | ||
684 | .of_match_table = brcmstb_i2c_of_match, | ||
685 | .pm = &brcmstb_i2c_pm, | ||
686 | }, | ||
687 | .probe = brcmstb_i2c_probe, | ||
688 | .remove = brcmstb_i2c_remove, | ||
689 | }; | ||
690 | module_platform_driver(brcmstb_i2c_driver); | ||
691 | |||
692 | MODULE_AUTHOR("Kamal Dasu <kdasu@broadcom.com>"); | ||
693 | MODULE_DESCRIPTION("Broadcom Settop I2C Driver"); | ||
694 | MODULE_LICENSE("GPL v2"); | ||