Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
0004  *
0005  * Original author:
0006  * Ben Collins <bcollins@ubuntu.com>
0007  *
0008  * Additional work by:
0009  * John Brooks <john.brooks@bluecherry.net>
0010  */
0011 
0012 /* XXX: The SOLO6x10 i2c does not have separate interrupts for each i2c
0013  * channel. The bus can only handle one i2c event at a time. The below handles
0014  * this all wrong. We should be using the status registers to see if the bus
0015  * is in use, and have a global lock to check the status register. Also,
0016  * the bulk of the work should be handled out-of-interrupt. The ugly loops
0017  * that occur during interrupt scare me. The ISR should merely signal
0018  * thread context, ACK the interrupt, and move on. -- BenC */
0019 
0020 #include <linux/kernel.h>
0021 #include <linux/sched/signal.h>
0022 
0023 #include "solo6x10.h"
0024 
0025 u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off)
0026 {
0027     struct i2c_msg msgs[2];
0028     u8 data;
0029 
0030     msgs[0].flags = 0;
0031     msgs[0].addr = addr;
0032     msgs[0].len = 1;
0033     msgs[0].buf = &off;
0034 
0035     msgs[1].flags = I2C_M_RD;
0036     msgs[1].addr = addr;
0037     msgs[1].len = 1;
0038     msgs[1].buf = &data;
0039 
0040     i2c_transfer(&solo_dev->i2c_adap[id], msgs, 2);
0041 
0042     return data;
0043 }
0044 
0045 void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr,
0046             u8 off, u8 data)
0047 {
0048     struct i2c_msg msgs;
0049     u8 buf[2];
0050 
0051     buf[0] = off;
0052     buf[1] = data;
0053     msgs.flags = 0;
0054     msgs.addr = addr;
0055     msgs.len = 2;
0056     msgs.buf = buf;
0057 
0058     i2c_transfer(&solo_dev->i2c_adap[id], &msgs, 1);
0059 }
0060 
0061 static void solo_i2c_flush(struct solo_dev *solo_dev, int wr)
0062 {
0063     u32 ctrl;
0064 
0065     ctrl = SOLO_IIC_CH_SET(solo_dev->i2c_id);
0066 
0067     if (solo_dev->i2c_state == IIC_STATE_START)
0068         ctrl |= SOLO_IIC_START;
0069 
0070     if (wr) {
0071         ctrl |= SOLO_IIC_WRITE;
0072     } else {
0073         ctrl |= SOLO_IIC_READ;
0074         if (!(solo_dev->i2c_msg->flags & I2C_M_NO_RD_ACK))
0075             ctrl |= SOLO_IIC_ACK_EN;
0076     }
0077 
0078     if (solo_dev->i2c_msg_ptr == solo_dev->i2c_msg->len)
0079         ctrl |= SOLO_IIC_STOP;
0080 
0081     solo_reg_write(solo_dev, SOLO_IIC_CTRL, ctrl);
0082 }
0083 
0084 static void solo_i2c_start(struct solo_dev *solo_dev)
0085 {
0086     u32 addr = solo_dev->i2c_msg->addr << 1;
0087 
0088     if (solo_dev->i2c_msg->flags & I2C_M_RD)
0089         addr |= 1;
0090 
0091     solo_dev->i2c_state = IIC_STATE_START;
0092     solo_reg_write(solo_dev, SOLO_IIC_TXD, addr);
0093     solo_i2c_flush(solo_dev, 1);
0094 }
0095 
0096 static void solo_i2c_stop(struct solo_dev *solo_dev)
0097 {
0098     solo_irq_off(solo_dev, SOLO_IRQ_IIC);
0099     solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
0100     solo_dev->i2c_state = IIC_STATE_STOP;
0101     wake_up(&solo_dev->i2c_wait);
0102 }
0103 
0104 static int solo_i2c_handle_read(struct solo_dev *solo_dev)
0105 {
0106 prepare_read:
0107     if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
0108         solo_i2c_flush(solo_dev, 0);
0109         return 0;
0110     }
0111 
0112     solo_dev->i2c_msg_ptr = 0;
0113     solo_dev->i2c_msg++;
0114     solo_dev->i2c_msg_num--;
0115 
0116     if (solo_dev->i2c_msg_num == 0) {
0117         solo_i2c_stop(solo_dev);
0118         return 0;
0119     }
0120 
0121     if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
0122         solo_i2c_start(solo_dev);
0123     } else {
0124         if (solo_dev->i2c_msg->flags & I2C_M_RD)
0125             goto prepare_read;
0126         else
0127             solo_i2c_stop(solo_dev);
0128     }
0129 
0130     return 0;
0131 }
0132 
0133 static int solo_i2c_handle_write(struct solo_dev *solo_dev)
0134 {
0135 retry_write:
0136     if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
0137         solo_reg_write(solo_dev, SOLO_IIC_TXD,
0138                    solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr]);
0139         solo_dev->i2c_msg_ptr++;
0140         solo_i2c_flush(solo_dev, 1);
0141         return 0;
0142     }
0143 
0144     solo_dev->i2c_msg_ptr = 0;
0145     solo_dev->i2c_msg++;
0146     solo_dev->i2c_msg_num--;
0147 
0148     if (solo_dev->i2c_msg_num == 0) {
0149         solo_i2c_stop(solo_dev);
0150         return 0;
0151     }
0152 
0153     if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
0154         solo_i2c_start(solo_dev);
0155     } else {
0156         if (solo_dev->i2c_msg->flags & I2C_M_RD)
0157             solo_i2c_stop(solo_dev);
0158         else
0159             goto retry_write;
0160     }
0161 
0162     return 0;
0163 }
0164 
0165 int solo_i2c_isr(struct solo_dev *solo_dev)
0166 {
0167     u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL);
0168     int ret = -EINVAL;
0169 
0170 
0171     if (CHK_FLAGS(status, SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR)
0172         || solo_dev->i2c_id < 0) {
0173         solo_i2c_stop(solo_dev);
0174         return -ENXIO;
0175     }
0176 
0177     switch (solo_dev->i2c_state) {
0178     case IIC_STATE_START:
0179         if (solo_dev->i2c_msg->flags & I2C_M_RD) {
0180             solo_dev->i2c_state = IIC_STATE_READ;
0181             ret = solo_i2c_handle_read(solo_dev);
0182             break;
0183         }
0184 
0185         solo_dev->i2c_state = IIC_STATE_WRITE;
0186         fallthrough;
0187     case IIC_STATE_WRITE:
0188         ret = solo_i2c_handle_write(solo_dev);
0189         break;
0190 
0191     case IIC_STATE_READ:
0192         solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr] =
0193             solo_reg_read(solo_dev, SOLO_IIC_RXD);
0194         solo_dev->i2c_msg_ptr++;
0195 
0196         ret = solo_i2c_handle_read(solo_dev);
0197         break;
0198 
0199     default:
0200         solo_i2c_stop(solo_dev);
0201     }
0202 
0203     return ret;
0204 }
0205 
0206 static int solo_i2c_master_xfer(struct i2c_adapter *adap,
0207                 struct i2c_msg msgs[], int num)
0208 {
0209     struct solo_dev *solo_dev = adap->algo_data;
0210     unsigned long timeout;
0211     int ret;
0212     int i;
0213     DEFINE_WAIT(wait);
0214 
0215     for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
0216         if (&solo_dev->i2c_adap[i] == adap)
0217             break;
0218     }
0219 
0220     if (i == SOLO_I2C_ADAPTERS)
0221         return num; /* XXX Right return value for failure? */
0222 
0223     mutex_lock(&solo_dev->i2c_mutex);
0224     solo_dev->i2c_id = i;
0225     solo_dev->i2c_msg = msgs;
0226     solo_dev->i2c_msg_num = num;
0227     solo_dev->i2c_msg_ptr = 0;
0228 
0229     solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
0230     solo_irq_on(solo_dev, SOLO_IRQ_IIC);
0231     solo_i2c_start(solo_dev);
0232 
0233     timeout = HZ / 2;
0234 
0235     for (;;) {
0236         prepare_to_wait(&solo_dev->i2c_wait, &wait,
0237                 TASK_INTERRUPTIBLE);
0238 
0239         if (solo_dev->i2c_state == IIC_STATE_STOP)
0240             break;
0241 
0242         timeout = schedule_timeout(timeout);
0243         if (!timeout)
0244             break;
0245 
0246         if (signal_pending(current))
0247             break;
0248     }
0249 
0250     finish_wait(&solo_dev->i2c_wait, &wait);
0251     ret = num - solo_dev->i2c_msg_num;
0252     solo_dev->i2c_state = IIC_STATE_IDLE;
0253     solo_dev->i2c_id = -1;
0254 
0255     mutex_unlock(&solo_dev->i2c_mutex);
0256 
0257     return ret;
0258 }
0259 
0260 static u32 solo_i2c_functionality(struct i2c_adapter *adap)
0261 {
0262     return I2C_FUNC_I2C;
0263 }
0264 
0265 static const struct i2c_algorithm solo_i2c_algo = {
0266     .master_xfer    = solo_i2c_master_xfer,
0267     .functionality  = solo_i2c_functionality,
0268 };
0269 
0270 int solo_i2c_init(struct solo_dev *solo_dev)
0271 {
0272     int i;
0273     int ret;
0274 
0275     solo_reg_write(solo_dev, SOLO_IIC_CFG,
0276                SOLO_IIC_PRESCALE(8) | SOLO_IIC_ENABLE);
0277 
0278     solo_dev->i2c_id = -1;
0279     solo_dev->i2c_state = IIC_STATE_IDLE;
0280     init_waitqueue_head(&solo_dev->i2c_wait);
0281     mutex_init(&solo_dev->i2c_mutex);
0282 
0283     for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
0284         struct i2c_adapter *adap = &solo_dev->i2c_adap[i];
0285 
0286         snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d",
0287              SOLO6X10_NAME, i);
0288         adap->algo = &solo_i2c_algo;
0289         adap->algo_data = solo_dev;
0290         adap->retries = 1;
0291         adap->dev.parent = &solo_dev->pdev->dev;
0292 
0293         ret = i2c_add_adapter(adap);
0294         if (ret) {
0295             adap->algo_data = NULL;
0296             break;
0297         }
0298     }
0299 
0300     if (ret) {
0301         for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
0302             if (!solo_dev->i2c_adap[i].algo_data)
0303                 break;
0304             i2c_del_adapter(&solo_dev->i2c_adap[i]);
0305             solo_dev->i2c_adap[i].algo_data = NULL;
0306         }
0307         return ret;
0308     }
0309 
0310     return 0;
0311 }
0312 
0313 void solo_i2c_exit(struct solo_dev *solo_dev)
0314 {
0315     int i;
0316 
0317     for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
0318         if (!solo_dev->i2c_adap[i].algo_data)
0319             continue;
0320         i2c_del_adapter(&solo_dev->i2c_adap[i]);
0321         solo_dev->i2c_adap[i].algo_data = NULL;
0322     }
0323 }