i2c-digicolor.c (8054B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * I2C bus driver for Conexant Digicolor SoCs 4 * 5 * Author: Baruch Siach <baruch@tkos.co.il> 6 * 7 * Copyright (C) 2015 Paradox Innovation Ltd. 8 */ 9 10#include <linux/clk.h> 11#include <linux/completion.h> 12#include <linux/delay.h> 13#include <linux/i2c.h> 14#include <linux/interrupt.h> 15#include <linux/io.h> 16#include <linux/kernel.h> 17#include <linux/module.h> 18#include <linux/of.h> 19#include <linux/platform_device.h> 20 21#define TIMEOUT_MS 100 22 23#define II_CONTROL 0x0 24#define II_CONTROL_LOCAL_RESET BIT(0) 25 26#define II_CLOCKTIME 0x1 27 28#define II_COMMAND 0x2 29#define II_CMD_START 1 30#define II_CMD_RESTART 2 31#define II_CMD_SEND_ACK 3 32#define II_CMD_GET_ACK 6 33#define II_CMD_GET_NOACK 7 34#define II_CMD_STOP 10 35#define II_COMMAND_GO BIT(7) 36#define II_COMMAND_COMPLETION_STATUS(r) (((r) >> 5) & 3) 37#define II_CMD_STATUS_NORMAL 0 38#define II_CMD_STATUS_ACK_GOOD 1 39#define II_CMD_STATUS_ACK_BAD 2 40#define II_CMD_STATUS_ABORT 3 41 42#define II_DATA 0x3 43#define II_INTFLAG_CLEAR 0x8 44#define II_INTENABLE 0xa 45 46struct dc_i2c { 47 struct i2c_adapter adap; 48 struct device *dev; 49 void __iomem *regs; 50 struct clk *clk; 51 unsigned int frequency; 52 53 struct i2c_msg *msg; 54 unsigned int msgbuf_ptr; 55 int last; 56 spinlock_t lock; 57 struct completion done; 58 int state; 59 int error; 60}; 61 62enum { 63 STATE_IDLE, 64 STATE_START, 65 STATE_ADDR, 66 STATE_WRITE, 67 STATE_READ, 68 STATE_STOP, 69}; 70 71static void dc_i2c_cmd(struct dc_i2c *i2c, u8 cmd) 72{ 73 writeb_relaxed(cmd | II_COMMAND_GO, i2c->regs + II_COMMAND); 74} 75 76static u8 dc_i2c_addr_cmd(struct i2c_msg *msg) 77{ 78 u8 addr = (msg->addr & 0x7f) << 1; 79 80 if (msg->flags & I2C_M_RD) 81 addr |= 1; 82 83 return addr; 84} 85 86static void dc_i2c_data(struct dc_i2c *i2c, u8 data) 87{ 88 writeb_relaxed(data, i2c->regs + II_DATA); 89} 90 91static void dc_i2c_write_byte(struct dc_i2c *i2c, u8 byte) 92{ 93 dc_i2c_data(i2c, byte); 94 dc_i2c_cmd(i2c, II_CMD_SEND_ACK); 95} 96 97static void dc_i2c_write_buf(struct dc_i2c *i2c) 98{ 99 dc_i2c_write_byte(i2c, i2c->msg->buf[i2c->msgbuf_ptr++]); 100} 101 102static void dc_i2c_next_read(struct dc_i2c *i2c) 103{ 104 bool last = (i2c->msgbuf_ptr + 1 == i2c->msg->len); 105 106 dc_i2c_cmd(i2c, last ? II_CMD_GET_NOACK : II_CMD_GET_ACK); 107} 108 109static void dc_i2c_stop(struct dc_i2c *i2c) 110{ 111 i2c->state = STATE_STOP; 112 if (i2c->last) 113 dc_i2c_cmd(i2c, II_CMD_STOP); 114 else 115 complete(&i2c->done); 116} 117 118static u8 dc_i2c_read_byte(struct dc_i2c *i2c) 119{ 120 return readb_relaxed(i2c->regs + II_DATA); 121} 122 123static void dc_i2c_read_buf(struct dc_i2c *i2c) 124{ 125 i2c->msg->buf[i2c->msgbuf_ptr++] = dc_i2c_read_byte(i2c); 126 dc_i2c_next_read(i2c); 127} 128 129static void dc_i2c_set_irq(struct dc_i2c *i2c, int enable) 130{ 131 if (enable) 132 writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR); 133 writeb_relaxed(!!enable, i2c->regs + II_INTENABLE); 134} 135 136static int dc_i2c_cmd_status(struct dc_i2c *i2c) 137{ 138 u8 cmd = readb_relaxed(i2c->regs + II_COMMAND); 139 140 return II_COMMAND_COMPLETION_STATUS(cmd); 141} 142 143static void dc_i2c_start_msg(struct dc_i2c *i2c, int first) 144{ 145 struct i2c_msg *msg = i2c->msg; 146 147 if (!(msg->flags & I2C_M_NOSTART)) { 148 i2c->state = STATE_START; 149 dc_i2c_cmd(i2c, first ? II_CMD_START : II_CMD_RESTART); 150 } else if (msg->flags & I2C_M_RD) { 151 i2c->state = STATE_READ; 152 dc_i2c_next_read(i2c); 153 } else { 154 i2c->state = STATE_WRITE; 155 dc_i2c_write_buf(i2c); 156 } 157} 158 159static irqreturn_t dc_i2c_irq(int irq, void *dev_id) 160{ 161 struct dc_i2c *i2c = dev_id; 162 int cmd_status = dc_i2c_cmd_status(i2c); 163 u8 addr_cmd; 164 165 writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR); 166 167 spin_lock(&i2c->lock); 168 169 if (cmd_status == II_CMD_STATUS_ACK_BAD 170 || cmd_status == II_CMD_STATUS_ABORT) { 171 i2c->error = -EIO; 172 complete(&i2c->done); 173 goto out; 174 } 175 176 switch (i2c->state) { 177 case STATE_START: 178 addr_cmd = dc_i2c_addr_cmd(i2c->msg); 179 dc_i2c_write_byte(i2c, addr_cmd); 180 i2c->state = STATE_ADDR; 181 break; 182 case STATE_ADDR: 183 if (i2c->msg->flags & I2C_M_RD) { 184 dc_i2c_next_read(i2c); 185 i2c->state = STATE_READ; 186 break; 187 } 188 i2c->state = STATE_WRITE; 189 fallthrough; 190 case STATE_WRITE: 191 if (i2c->msgbuf_ptr < i2c->msg->len) 192 dc_i2c_write_buf(i2c); 193 else 194 dc_i2c_stop(i2c); 195 break; 196 case STATE_READ: 197 if (i2c->msgbuf_ptr < i2c->msg->len) 198 dc_i2c_read_buf(i2c); 199 else 200 dc_i2c_stop(i2c); 201 break; 202 case STATE_STOP: 203 i2c->state = STATE_IDLE; 204 complete(&i2c->done); 205 break; 206 } 207 208out: 209 spin_unlock(&i2c->lock); 210 return IRQ_HANDLED; 211} 212 213static int dc_i2c_xfer_msg(struct dc_i2c *i2c, struct i2c_msg *msg, int first, 214 int last) 215{ 216 unsigned long timeout = msecs_to_jiffies(TIMEOUT_MS); 217 unsigned long flags; 218 219 spin_lock_irqsave(&i2c->lock, flags); 220 i2c->msg = msg; 221 i2c->msgbuf_ptr = 0; 222 i2c->last = last; 223 i2c->error = 0; 224 225 reinit_completion(&i2c->done); 226 dc_i2c_set_irq(i2c, 1); 227 dc_i2c_start_msg(i2c, first); 228 spin_unlock_irqrestore(&i2c->lock, flags); 229 230 timeout = wait_for_completion_timeout(&i2c->done, timeout); 231 dc_i2c_set_irq(i2c, 0); 232 if (timeout == 0) { 233 i2c->state = STATE_IDLE; 234 return -ETIMEDOUT; 235 } 236 237 if (i2c->error) 238 return i2c->error; 239 240 return 0; 241} 242 243static int dc_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 244{ 245 struct dc_i2c *i2c = adap->algo_data; 246 int i, ret; 247 248 for (i = 0; i < num; i++) { 249 ret = dc_i2c_xfer_msg(i2c, &msgs[i], i == 0, i == num - 1); 250 if (ret) 251 return ret; 252 } 253 254 return num; 255} 256 257static int dc_i2c_init_hw(struct dc_i2c *i2c) 258{ 259 unsigned long clk_rate = clk_get_rate(i2c->clk); 260 unsigned int clocktime; 261 262 writeb_relaxed(II_CONTROL_LOCAL_RESET, i2c->regs + II_CONTROL); 263 udelay(100); 264 writeb_relaxed(0, i2c->regs + II_CONTROL); 265 udelay(100); 266 267 clocktime = DIV_ROUND_UP(clk_rate, 64 * i2c->frequency); 268 if (clocktime < 1 || clocktime > 0xff) { 269 dev_err(i2c->dev, "can't set bus speed of %u Hz\n", 270 i2c->frequency); 271 return -EINVAL; 272 } 273 writeb_relaxed(clocktime - 1, i2c->regs + II_CLOCKTIME); 274 275 return 0; 276} 277 278static u32 dc_i2c_func(struct i2c_adapter *adap) 279{ 280 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART; 281} 282 283static const struct i2c_algorithm dc_i2c_algorithm = { 284 .master_xfer = dc_i2c_xfer, 285 .functionality = dc_i2c_func, 286}; 287 288static int dc_i2c_probe(struct platform_device *pdev) 289{ 290 struct device_node *np = pdev->dev.of_node; 291 struct dc_i2c *i2c; 292 int ret = 0, irq; 293 294 i2c = devm_kzalloc(&pdev->dev, sizeof(struct dc_i2c), GFP_KERNEL); 295 if (!i2c) 296 return -ENOMEM; 297 298 if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", 299 &i2c->frequency)) 300 i2c->frequency = I2C_MAX_STANDARD_MODE_FREQ; 301 302 i2c->dev = &pdev->dev; 303 platform_set_drvdata(pdev, i2c); 304 305 spin_lock_init(&i2c->lock); 306 init_completion(&i2c->done); 307 308 i2c->clk = devm_clk_get(&pdev->dev, NULL); 309 if (IS_ERR(i2c->clk)) 310 return PTR_ERR(i2c->clk); 311 312 i2c->regs = devm_platform_ioremap_resource(pdev, 0); 313 if (IS_ERR(i2c->regs)) 314 return PTR_ERR(i2c->regs); 315 316 irq = platform_get_irq(pdev, 0); 317 if (irq < 0) 318 return irq; 319 320 ret = devm_request_irq(&pdev->dev, irq, dc_i2c_irq, 0, 321 dev_name(&pdev->dev), i2c); 322 if (ret < 0) 323 return ret; 324 325 strlcpy(i2c->adap.name, "Conexant Digicolor I2C adapter", 326 sizeof(i2c->adap.name)); 327 i2c->adap.owner = THIS_MODULE; 328 i2c->adap.algo = &dc_i2c_algorithm; 329 i2c->adap.dev.parent = &pdev->dev; 330 i2c->adap.dev.of_node = np; 331 i2c->adap.algo_data = i2c; 332 333 ret = dc_i2c_init_hw(i2c); 334 if (ret) 335 return ret; 336 337 ret = clk_prepare_enable(i2c->clk); 338 if (ret < 0) 339 return ret; 340 341 ret = i2c_add_adapter(&i2c->adap); 342 if (ret < 0) { 343 clk_disable_unprepare(i2c->clk); 344 return ret; 345 } 346 347 return 0; 348} 349 350static int dc_i2c_remove(struct platform_device *pdev) 351{ 352 struct dc_i2c *i2c = platform_get_drvdata(pdev); 353 354 i2c_del_adapter(&i2c->adap); 355 clk_disable_unprepare(i2c->clk); 356 357 return 0; 358} 359 360static const struct of_device_id dc_i2c_match[] = { 361 { .compatible = "cnxt,cx92755-i2c" }, 362 { }, 363}; 364MODULE_DEVICE_TABLE(of, dc_i2c_match); 365 366static struct platform_driver dc_i2c_driver = { 367 .probe = dc_i2c_probe, 368 .remove = dc_i2c_remove, 369 .driver = { 370 .name = "digicolor-i2c", 371 .of_match_table = dc_i2c_match, 372 }, 373}; 374module_platform_driver(dc_i2c_driver); 375 376MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); 377MODULE_DESCRIPTION("Conexant Digicolor I2C master driver"); 378MODULE_LICENSE("GPL v2");