Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: add bcm2835 driver

This implements a very basic I2C host driver for the BCM2835 SoC. Missing
features so far are:

* 10-bit addressing.
* DMA.

Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
Signed-off-by: Wolfram Sang <wolfram@the-dreams.de>

authored by

Stephen Warren and committed by
Wolfram Sang
f3b54b9a cb7f07a4

+375
+20
Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
··· 1 + Broadcom BCM2835 I2C controller 2 + 3 + Required properties: 4 + - compatible : Should be "brcm,bcm2835-i2c". 5 + - reg: Should contain register location and length. 6 + - interrupts: Should contain interrupt. 7 + - clocks : The clock feeding the I2C controller. 8 + 9 + Recommended properties: 10 + - clock-frequency : desired I2C bus clock frequency in Hz. 11 + 12 + Example: 13 + 14 + i2c@20205000 { 15 + compatible = "brcm,bcm2835-i2c"; 16 + reg = <0x7e205000 0x1000>; 17 + interrupts = <2 21>; 18 + clocks = <&clk_i2c>; 19 + clock-frequency = <100000>; 20 + };
+12
drivers/i2c/busses/Kconfig
··· 330 330 This driver can also be built as a module. If so, the module 331 331 will be called i2c-au1550. 332 332 333 + config I2C_BCM2835 334 + tristate "Broadcom BCM2835 I2C controller" 335 + depends on ARCH_BCM2835 336 + help 337 + If you say yes to this option, support will be included for the 338 + BCM2835 I2C controller. 339 + 340 + If you don't know what to do here, say N. 341 + 342 + This support is also available as a module. If so, the module 343 + will be called i2c-bcm2835. 344 + 333 345 config I2C_BLACKFIN_TWI 334 346 tristate "Blackfin TWI I2C support" 335 347 depends on BLACKFIN
+1
drivers/i2c/busses/Makefile
··· 31 31 # Embedded system I2C/SMBus host controller drivers 32 32 obj-$(CONFIG_I2C_AT91) += i2c-at91.o 33 33 obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o 34 + obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o 34 35 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o 35 36 obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o 36 37 obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
+342
drivers/i2c/busses/i2c-bcm2835.c
··· 1 + /* 2 + * BCM2835 master mode driver 3 + * 4 + * This software is licensed under the terms of the GNU General Public 5 + * License version 2, as published by the Free Software Foundation, and 6 + * may be copied, distributed, and modified under those terms. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * 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/completion.h> 16 + #include <linux/err.h> 17 + #include <linux/i2c.h> 18 + #include <linux/interrupt.h> 19 + #include <linux/io.h> 20 + #include <linux/module.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/slab.h> 23 + 24 + #define BCM2835_I2C_C 0x0 25 + #define BCM2835_I2C_S 0x4 26 + #define BCM2835_I2C_DLEN 0x8 27 + #define BCM2835_I2C_A 0xc 28 + #define BCM2835_I2C_FIFO 0x10 29 + #define BCM2835_I2C_DIV 0x14 30 + #define BCM2835_I2C_DEL 0x18 31 + #define BCM2835_I2C_CLKT 0x1c 32 + 33 + #define BCM2835_I2C_C_READ BIT(0) 34 + #define BCM2835_I2C_C_CLEAR BIT(4) /* bits 4 and 5 both clear */ 35 + #define BCM2835_I2C_C_ST BIT(7) 36 + #define BCM2835_I2C_C_INTD BIT(8) 37 + #define BCM2835_I2C_C_INTT BIT(9) 38 + #define BCM2835_I2C_C_INTR BIT(10) 39 + #define BCM2835_I2C_C_I2CEN BIT(15) 40 + 41 + #define BCM2835_I2C_S_TA BIT(0) 42 + #define BCM2835_I2C_S_DONE BIT(1) 43 + #define BCM2835_I2C_S_TXW BIT(2) 44 + #define BCM2835_I2C_S_RXR BIT(3) 45 + #define BCM2835_I2C_S_TXD BIT(4) 46 + #define BCM2835_I2C_S_RXD BIT(5) 47 + #define BCM2835_I2C_S_TXE BIT(6) 48 + #define BCM2835_I2C_S_RXF BIT(7) 49 + #define BCM2835_I2C_S_ERR BIT(8) 50 + #define BCM2835_I2C_S_CLKT BIT(9) 51 + #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ 52 + 53 + #define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000)) 54 + 55 + struct bcm2835_i2c_dev { 56 + struct device *dev; 57 + void __iomem *regs; 58 + struct clk *clk; 59 + int irq; 60 + struct i2c_adapter adapter; 61 + struct completion completion; 62 + u32 msg_err; 63 + u8 *msg_buf; 64 + size_t msg_buf_remaining; 65 + }; 66 + 67 + static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, 68 + u32 reg, u32 val) 69 + { 70 + writel(val, i2c_dev->regs + reg); 71 + } 72 + 73 + static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) 74 + { 75 + return readl(i2c_dev->regs + reg); 76 + } 77 + 78 + static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) 79 + { 80 + u32 val; 81 + 82 + while (i2c_dev->msg_buf_remaining) { 83 + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); 84 + if (!(val & BCM2835_I2C_S_TXD)) 85 + break; 86 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_FIFO, 87 + *i2c_dev->msg_buf); 88 + i2c_dev->msg_buf++; 89 + i2c_dev->msg_buf_remaining--; 90 + } 91 + } 92 + 93 + static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev) 94 + { 95 + u32 val; 96 + 97 + while (i2c_dev->msg_buf_remaining) { 98 + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); 99 + if (!(val & BCM2835_I2C_S_RXD)) 100 + break; 101 + *i2c_dev->msg_buf = bcm2835_i2c_readl(i2c_dev, 102 + BCM2835_I2C_FIFO); 103 + i2c_dev->msg_buf++; 104 + i2c_dev->msg_buf_remaining--; 105 + } 106 + } 107 + 108 + static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) 109 + { 110 + struct bcm2835_i2c_dev *i2c_dev = data; 111 + u32 val, err; 112 + 113 + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); 114 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val); 115 + 116 + err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); 117 + if (err) { 118 + i2c_dev->msg_err = err; 119 + complete(&i2c_dev->completion); 120 + return IRQ_HANDLED; 121 + } 122 + 123 + if (val & BCM2835_I2C_S_RXD) { 124 + bcm2835_drain_rxfifo(i2c_dev); 125 + if (!(val & BCM2835_I2C_S_DONE)) 126 + return IRQ_HANDLED; 127 + } 128 + 129 + if (val & BCM2835_I2C_S_DONE) { 130 + if (i2c_dev->msg_buf_remaining) 131 + i2c_dev->msg_err = BCM2835_I2C_S_LEN; 132 + else 133 + i2c_dev->msg_err = 0; 134 + complete(&i2c_dev->completion); 135 + return IRQ_HANDLED; 136 + } 137 + 138 + if (val & BCM2835_I2C_S_TXD) { 139 + bcm2835_fill_txfifo(i2c_dev); 140 + return IRQ_HANDLED; 141 + } 142 + 143 + return IRQ_NONE; 144 + } 145 + 146 + static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, 147 + struct i2c_msg *msg) 148 + { 149 + u32 c; 150 + int time_left; 151 + 152 + i2c_dev->msg_buf = msg->buf; 153 + i2c_dev->msg_buf_remaining = msg->len; 154 + INIT_COMPLETION(i2c_dev->completion); 155 + 156 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); 157 + 158 + if (msg->flags & I2C_M_RD) { 159 + c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR; 160 + } else { 161 + c = BCM2835_I2C_C_INTT; 162 + bcm2835_fill_txfifo(i2c_dev); 163 + } 164 + c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN; 165 + 166 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); 167 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); 168 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); 169 + 170 + time_left = wait_for_completion_timeout(&i2c_dev->completion, 171 + BCM2835_I2C_TIMEOUT); 172 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); 173 + if (!time_left) { 174 + dev_err(i2c_dev->dev, "i2c transfer timed out\n"); 175 + return -ETIMEDOUT; 176 + } 177 + 178 + if (likely(!i2c_dev->msg_err)) 179 + return 0; 180 + 181 + if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) && 182 + (msg->flags & I2C_M_IGNORE_NAK)) 183 + return 0; 184 + 185 + dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); 186 + 187 + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) 188 + return -EREMOTEIO; 189 + else 190 + return -EIO; 191 + } 192 + 193 + static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], 194 + int num) 195 + { 196 + struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); 197 + int i; 198 + int ret = 0; 199 + 200 + for (i = 0; i < num; i++) { 201 + ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]); 202 + if (ret) 203 + break; 204 + } 205 + 206 + return ret ?: i; 207 + } 208 + 209 + static u32 bcm2835_i2c_func(struct i2c_adapter *adap) 210 + { 211 + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 212 + } 213 + 214 + static const struct i2c_algorithm bcm2835_i2c_algo = { 215 + .master_xfer = bcm2835_i2c_xfer, 216 + .functionality = bcm2835_i2c_func, 217 + }; 218 + 219 + static int bcm2835_i2c_probe(struct platform_device *pdev) 220 + { 221 + struct bcm2835_i2c_dev *i2c_dev; 222 + struct resource *mem, *requested, *irq; 223 + u32 bus_clk_rate, divider; 224 + int ret; 225 + struct i2c_adapter *adap; 226 + 227 + i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); 228 + if (!i2c_dev) { 229 + dev_err(&pdev->dev, "Cannot allocate i2c_dev\n"); 230 + return -ENOMEM; 231 + } 232 + platform_set_drvdata(pdev, i2c_dev); 233 + i2c_dev->dev = &pdev->dev; 234 + init_completion(&i2c_dev->completion); 235 + 236 + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 237 + if (!mem) { 238 + dev_err(&pdev->dev, "No mem resource\n"); 239 + return -ENODEV; 240 + } 241 + 242 + requested = devm_request_mem_region(&pdev->dev, mem->start, 243 + resource_size(mem), 244 + dev_name(&pdev->dev)); 245 + if (!requested) { 246 + dev_err(&pdev->dev, "Could not claim register region\n"); 247 + return -EBUSY; 248 + } 249 + 250 + i2c_dev->regs = devm_ioremap(&pdev->dev, mem->start, 251 + resource_size(mem)); 252 + if (!i2c_dev->regs) { 253 + dev_err(&pdev->dev, "Could not map registers\n"); 254 + return -ENOMEM; 255 + } 256 + 257 + i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); 258 + if (IS_ERR(i2c_dev->clk)) { 259 + dev_err(&pdev->dev, "Could not get clock\n"); 260 + return PTR_ERR(i2c_dev->clk); 261 + } 262 + 263 + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", 264 + &bus_clk_rate); 265 + if (ret < 0) { 266 + dev_warn(&pdev->dev, 267 + "Could not read clock-frequency property\n"); 268 + bus_clk_rate = 100000; 269 + } 270 + 271 + divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate); 272 + /* 273 + * Per the datasheet, the register is always interpreted as an even 274 + * number, by rounding down. In other words, the LSB is ignored. So, 275 + * if the LSB is set, increment the divider to avoid any issue. 276 + */ 277 + if (divider & 1) 278 + divider++; 279 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); 280 + 281 + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 282 + if (!irq) { 283 + dev_err(&pdev->dev, "No IRQ resource\n"); 284 + return -ENODEV; 285 + } 286 + i2c_dev->irq = irq->start; 287 + 288 + ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED, 289 + dev_name(&pdev->dev), i2c_dev); 290 + if (ret) { 291 + dev_err(&pdev->dev, "Could not request IRQ\n"); 292 + return -ENODEV; 293 + } 294 + 295 + adap = &i2c_dev->adapter; 296 + i2c_set_adapdata(adap, i2c_dev); 297 + adap->owner = THIS_MODULE; 298 + adap->class = I2C_CLASS_HWMON; 299 + strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name)); 300 + adap->algo = &bcm2835_i2c_algo; 301 + adap->dev.parent = &pdev->dev; 302 + 303 + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0); 304 + 305 + ret = i2c_add_adapter(adap); 306 + if (ret) 307 + free_irq(i2c_dev->irq, i2c_dev); 308 + 309 + return ret; 310 + } 311 + 312 + static int bcm2835_i2c_remove(struct platform_device *pdev) 313 + { 314 + struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev); 315 + 316 + free_irq(i2c_dev->irq, i2c_dev); 317 + i2c_del_adapter(&i2c_dev->adapter); 318 + 319 + return 0; 320 + } 321 + 322 + static const struct of_device_id bcm2835_i2c_of_match[] = { 323 + { .compatible = "brcm,bcm2835-i2c" }, 324 + {}, 325 + }; 326 + MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match); 327 + 328 + static struct platform_driver bcm2835_i2c_driver = { 329 + .probe = bcm2835_i2c_probe, 330 + .remove = bcm2835_i2c_remove, 331 + .driver = { 332 + .name = "i2c-bcm2835", 333 + .owner = THIS_MODULE, 334 + .of_match_table = bcm2835_i2c_of_match, 335 + }, 336 + }; 337 + module_platform_driver(bcm2835_i2c_driver); 338 + 339 + MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>"); 340 + MODULE_DESCRIPTION("BCM2835 I2C bus adapter"); 341 + MODULE_LICENSE("GPL v2"); 342 + MODULE_ALIAS("platform:i2c-bcm2835");