| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 6 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | | - * (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | 4 | */ |
|---|
| 14 | 5 | |
|---|
| 15 | 6 | #include <linux/clk.h> |
|---|
| .. | .. |
|---|
| 82 | 73 | #define UNIPHIER_FI2C_BYTE_WISE BIT(3) |
|---|
| 83 | 74 | #define UNIPHIER_FI2C_DEFER_STOP_COMP BIT(4) |
|---|
| 84 | 75 | |
|---|
| 85 | | -#define UNIPHIER_FI2C_DEFAULT_SPEED 100000 |
|---|
| 86 | | -#define UNIPHIER_FI2C_MAX_SPEED 400000 |
|---|
| 87 | 76 | #define UNIPHIER_FI2C_FIFO_SIZE 8 |
|---|
| 88 | 77 | |
|---|
| 89 | 78 | struct uniphier_fi2c_priv { |
|---|
| .. | .. |
|---|
| 117 | 106 | if (fifo_space-- <= 0) |
|---|
| 118 | 107 | break; |
|---|
| 119 | 108 | |
|---|
| 120 | | - dev_dbg(&priv->adap.dev, "write data: %02x\n", *priv->buf); |
|---|
| 121 | 109 | writel(*priv->buf++, priv->membase + UNIPHIER_FI2C_DTTX); |
|---|
| 122 | 110 | priv->len--; |
|---|
| 123 | 111 | } |
|---|
| .. | .. |
|---|
| 133 | 121 | break; |
|---|
| 134 | 122 | |
|---|
| 135 | 123 | *priv->buf++ = readl(priv->membase + UNIPHIER_FI2C_DTRX); |
|---|
| 136 | | - dev_dbg(&priv->adap.dev, "read data: %02x\n", priv->buf[-1]); |
|---|
| 137 | 124 | priv->len--; |
|---|
| 138 | 125 | } |
|---|
| 139 | 126 | } |
|---|
| .. | .. |
|---|
| 151 | 138 | |
|---|
| 152 | 139 | static void uniphier_fi2c_stop(struct uniphier_fi2c_priv *priv) |
|---|
| 153 | 140 | { |
|---|
| 154 | | - dev_dbg(&priv->adap.dev, "stop condition\n"); |
|---|
| 155 | | - |
|---|
| 156 | 141 | priv->enabled_irqs |= UNIPHIER_FI2C_INT_STOP; |
|---|
| 157 | 142 | uniphier_fi2c_set_irqs(priv); |
|---|
| 158 | 143 | writel(UNIPHIER_FI2C_CR_MST | UNIPHIER_FI2C_CR_STO, |
|---|
| .. | .. |
|---|
| 169 | 154 | irq_status = readl(priv->membase + UNIPHIER_FI2C_INT); |
|---|
| 170 | 155 | irq_status &= priv->enabled_irqs; |
|---|
| 171 | 156 | |
|---|
| 172 | | - dev_dbg(&priv->adap.dev, |
|---|
| 173 | | - "interrupt: enabled_irqs=%04x, irq_status=%04x\n", |
|---|
| 174 | | - priv->enabled_irqs, irq_status); |
|---|
| 175 | | - |
|---|
| 176 | 157 | if (irq_status & UNIPHIER_FI2C_INT_STOP) |
|---|
| 177 | 158 | goto complete; |
|---|
| 178 | 159 | |
|---|
| 179 | 160 | if (unlikely(irq_status & UNIPHIER_FI2C_INT_AL)) { |
|---|
| 180 | | - dev_dbg(&priv->adap.dev, "arbitration lost\n"); |
|---|
| 181 | 161 | priv->error = -EAGAIN; |
|---|
| 182 | 162 | goto complete; |
|---|
| 183 | 163 | } |
|---|
| 184 | 164 | |
|---|
| 185 | 165 | if (unlikely(irq_status & UNIPHIER_FI2C_INT_NA)) { |
|---|
| 186 | | - dev_dbg(&priv->adap.dev, "could not get ACK\n"); |
|---|
| 187 | 166 | priv->error = -ENXIO; |
|---|
| 188 | 167 | if (priv->flags & UNIPHIER_FI2C_RD) { |
|---|
| 189 | 168 | /* |
|---|
| .. | .. |
|---|
| 224 | 203 | if (unlikely(priv->flags & UNIPHIER_FI2C_MANUAL_NACK)) { |
|---|
| 225 | 204 | if (priv->len <= UNIPHIER_FI2C_FIFO_SIZE && |
|---|
| 226 | 205 | !(priv->flags & UNIPHIER_FI2C_BYTE_WISE)) { |
|---|
| 227 | | - dev_dbg(&priv->adap.dev, |
|---|
| 228 | | - "enable read byte count IRQ\n"); |
|---|
| 229 | 206 | priv->enabled_irqs |= UNIPHIER_FI2C_INT_RB; |
|---|
| 230 | 207 | uniphier_fi2c_set_irqs(priv); |
|---|
| 231 | 208 | priv->flags |= UNIPHIER_FI2C_BYTE_WISE; |
|---|
| 232 | 209 | } |
|---|
| 233 | | - if (priv->len <= 1) { |
|---|
| 234 | | - dev_dbg(&priv->adap.dev, "set NACK\n"); |
|---|
| 210 | + if (priv->len <= 1) |
|---|
| 235 | 211 | writel(UNIPHIER_FI2C_CR_MST | |
|---|
| 236 | 212 | UNIPHIER_FI2C_CR_NACK, |
|---|
| 237 | 213 | priv->membase + UNIPHIER_FI2C_CR); |
|---|
| 238 | | - } |
|---|
| 239 | 214 | } |
|---|
| 240 | 215 | |
|---|
| 241 | 216 | goto handled; |
|---|
| .. | .. |
|---|
| 269 | 244 | return IRQ_HANDLED; |
|---|
| 270 | 245 | } |
|---|
| 271 | 246 | |
|---|
| 272 | | -static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr) |
|---|
| 247 | +static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr, |
|---|
| 248 | + bool repeat) |
|---|
| 273 | 249 | { |
|---|
| 274 | 250 | priv->enabled_irqs |= UNIPHIER_FI2C_INT_TE; |
|---|
| 275 | 251 | uniphier_fi2c_set_irqs(priv); |
|---|
| .. | .. |
|---|
| 279 | 255 | /* set slave address */ |
|---|
| 280 | 256 | writel(UNIPHIER_FI2C_DTTX_CMD | addr << 1, |
|---|
| 281 | 257 | priv->membase + UNIPHIER_FI2C_DTTX); |
|---|
| 282 | | - /* first chunk of data */ |
|---|
| 283 | | - uniphier_fi2c_fill_txfifo(priv, true); |
|---|
| 258 | + /* |
|---|
| 259 | + * First chunk of data. For a repeated START condition, do not write |
|---|
| 260 | + * data to the TX fifo here to avoid the timing issue. |
|---|
| 261 | + */ |
|---|
| 262 | + if (!repeat) |
|---|
| 263 | + uniphier_fi2c_fill_txfifo(priv, true); |
|---|
| 284 | 264 | } |
|---|
| 285 | 265 | |
|---|
| 286 | 266 | static void uniphier_fi2c_rx_init(struct uniphier_fi2c_priv *priv, u16 addr) |
|---|
| .. | .. |
|---|
| 338 | 318 | bool is_read = msg->flags & I2C_M_RD; |
|---|
| 339 | 319 | unsigned long time_left, flags; |
|---|
| 340 | 320 | |
|---|
| 341 | | - dev_dbg(&adap->dev, "%s: addr=0x%02x, len=%d, repeat=%d, stop=%d\n", |
|---|
| 342 | | - is_read ? "receive" : "transmit", msg->addr, msg->len, |
|---|
| 343 | | - repeat, stop); |
|---|
| 344 | | - |
|---|
| 345 | 321 | priv->len = msg->len; |
|---|
| 346 | 322 | priv->buf = msg->buf; |
|---|
| 347 | 323 | priv->enabled_irqs = UNIPHIER_FI2C_INT_FAULTS; |
|---|
| .. | .. |
|---|
| 361 | 337 | if (is_read) |
|---|
| 362 | 338 | uniphier_fi2c_rx_init(priv, msg->addr); |
|---|
| 363 | 339 | else |
|---|
| 364 | | - uniphier_fi2c_tx_init(priv, msg->addr); |
|---|
| 340 | + uniphier_fi2c_tx_init(priv, msg->addr, repeat); |
|---|
| 365 | 341 | |
|---|
| 366 | | - dev_dbg(&adap->dev, "start condition\n"); |
|---|
| 367 | 342 | /* |
|---|
| 368 | 343 | * For a repeated START condition, writing a slave address to the FIFO |
|---|
| 369 | 344 | * kicks the controller. So, the UNIPHIER_FI2C_CR register should be |
|---|
| .. | .. |
|---|
| 387 | 362 | uniphier_fi2c_recover(priv); |
|---|
| 388 | 363 | return -ETIMEDOUT; |
|---|
| 389 | 364 | } |
|---|
| 390 | | - dev_dbg(&adap->dev, "complete\n"); |
|---|
| 391 | 365 | |
|---|
| 392 | 366 | if (unlikely(priv->flags & UNIPHIER_FI2C_DEFER_STOP_COMP)) { |
|---|
| 393 | 367 | u32 status; |
|---|
| .. | .. |
|---|
| 542 | 516 | { |
|---|
| 543 | 517 | struct device *dev = &pdev->dev; |
|---|
| 544 | 518 | struct uniphier_fi2c_priv *priv; |
|---|
| 545 | | - struct resource *regs; |
|---|
| 546 | 519 | u32 bus_speed; |
|---|
| 547 | 520 | unsigned long clk_rate; |
|---|
| 548 | 521 | int irq, ret; |
|---|
| .. | .. |
|---|
| 551 | 524 | if (!priv) |
|---|
| 552 | 525 | return -ENOMEM; |
|---|
| 553 | 526 | |
|---|
| 554 | | - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 555 | | - priv->membase = devm_ioremap_resource(dev, regs); |
|---|
| 527 | + priv->membase = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 556 | 528 | if (IS_ERR(priv->membase)) |
|---|
| 557 | 529 | return PTR_ERR(priv->membase); |
|---|
| 558 | 530 | |
|---|
| 559 | 531 | irq = platform_get_irq(pdev, 0); |
|---|
| 560 | | - if (irq < 0) { |
|---|
| 561 | | - dev_err(dev, "failed to get IRQ number\n"); |
|---|
| 532 | + if (irq < 0) |
|---|
| 562 | 533 | return irq; |
|---|
| 563 | | - } |
|---|
| 564 | 534 | |
|---|
| 565 | 535 | if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed)) |
|---|
| 566 | | - bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED; |
|---|
| 536 | + bus_speed = I2C_MAX_STANDARD_MODE_FREQ; |
|---|
| 567 | 537 | |
|---|
| 568 | | - if (!bus_speed || bus_speed > UNIPHIER_FI2C_MAX_SPEED) { |
|---|
| 538 | + if (!bus_speed || bus_speed > I2C_MAX_FAST_MODE_FREQ) { |
|---|
| 569 | 539 | dev_err(dev, "invalid clock-frequency %d\n", bus_speed); |
|---|
| 570 | 540 | return -EINVAL; |
|---|
| 571 | 541 | } |
|---|