Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Earthsoft PT3 driver
0004  *
0005  * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
0006  */
0007 #include <linux/delay.h>
0008 #include <linux/device.h>
0009 #include <linux/i2c.h>
0010 #include <linux/io.h>
0011 #include <linux/pci.h>
0012 
0013 #include "pt3.h"
0014 
0015 #define PT3_I2C_BASE  2048
0016 #define PT3_CMD_ADDR_NORMAL 0
0017 #define PT3_CMD_ADDR_INIT_DEMOD  4096
0018 #define PT3_CMD_ADDR_INIT_TUNER  (4096 + 2042)
0019 
0020 /* masks for I2C status register */
0021 #define STAT_SEQ_RUNNING 0x1
0022 #define STAT_SEQ_ERROR   0x6
0023 #define STAT_NO_SEQ      0x8
0024 
0025 #define PT3_I2C_RUN   (1 << 16)
0026 #define PT3_I2C_RESET (1 << 17)
0027 
0028 enum ctl_cmd {
0029     I_END,
0030     I_ADDRESS,
0031     I_CLOCK_L,
0032     I_CLOCK_H,
0033     I_DATA_L,
0034     I_DATA_H,
0035     I_RESET,
0036     I_SLEEP,
0037     I_DATA_L_NOP  = 0x08,
0038     I_DATA_H_NOP  = 0x0c,
0039     I_DATA_H_READ = 0x0d,
0040     I_DATA_H_ACK0 = 0x0e,
0041     I_DATA_H_ACK1 = 0x0f,
0042 };
0043 
0044 
0045 static void cmdbuf_add(struct pt3_i2cbuf *cbuf, enum ctl_cmd cmd)
0046 {
0047     int buf_idx;
0048 
0049     if ((cbuf->num_cmds % 2) == 0)
0050         cbuf->tmp = cmd;
0051     else {
0052         cbuf->tmp |= cmd << 4;
0053         buf_idx = cbuf->num_cmds / 2;
0054         if (buf_idx < ARRAY_SIZE(cbuf->data))
0055             cbuf->data[buf_idx] = cbuf->tmp;
0056     }
0057     cbuf->num_cmds++;
0058 }
0059 
0060 static void put_end(struct pt3_i2cbuf *cbuf)
0061 {
0062     cmdbuf_add(cbuf, I_END);
0063     if (cbuf->num_cmds % 2)
0064         cmdbuf_add(cbuf, I_END);
0065 }
0066 
0067 static void put_start(struct pt3_i2cbuf *cbuf)
0068 {
0069     cmdbuf_add(cbuf, I_DATA_H);
0070     cmdbuf_add(cbuf, I_CLOCK_H);
0071     cmdbuf_add(cbuf, I_DATA_L);
0072     cmdbuf_add(cbuf, I_CLOCK_L);
0073 }
0074 
0075 static void put_byte_write(struct pt3_i2cbuf *cbuf, u8 val)
0076 {
0077     u8 mask;
0078 
0079     for (mask = 0x80; mask > 0; mask >>= 1)
0080         cmdbuf_add(cbuf, (val & mask) ? I_DATA_H_NOP : I_DATA_L_NOP);
0081     cmdbuf_add(cbuf, I_DATA_H_ACK0);
0082 }
0083 
0084 static void put_byte_read(struct pt3_i2cbuf *cbuf, u32 size)
0085 {
0086     int i, j;
0087 
0088     for (i = 0; i < size; i++) {
0089         for (j = 0; j < 8; j++)
0090             cmdbuf_add(cbuf, I_DATA_H_READ);
0091         cmdbuf_add(cbuf, (i == size - 1) ? I_DATA_H_NOP : I_DATA_L_NOP);
0092     }
0093 }
0094 
0095 static void put_stop(struct pt3_i2cbuf *cbuf)
0096 {
0097     cmdbuf_add(cbuf, I_DATA_L);
0098     cmdbuf_add(cbuf, I_CLOCK_H);
0099     cmdbuf_add(cbuf, I_DATA_H);
0100 }
0101 
0102 
0103 /* translates msgs to internal commands for bit-banging */
0104 static void translate(struct pt3_i2cbuf *cbuf, struct i2c_msg *msgs, int num)
0105 {
0106     int i, j;
0107     bool rd;
0108 
0109     cbuf->num_cmds = 0;
0110     for (i = 0; i < num; i++) {
0111         rd = !!(msgs[i].flags & I2C_M_RD);
0112         put_start(cbuf);
0113         put_byte_write(cbuf, msgs[i].addr << 1 | rd);
0114         if (rd)
0115             put_byte_read(cbuf, msgs[i].len);
0116         else
0117             for (j = 0; j < msgs[i].len; j++)
0118                 put_byte_write(cbuf, msgs[i].buf[j]);
0119     }
0120     if (num > 0) {
0121         put_stop(cbuf);
0122         put_end(cbuf);
0123     }
0124 }
0125 
0126 static int wait_i2c_result(struct pt3_board *pt3, u32 *result, int max_wait)
0127 {
0128     int i;
0129     u32 v;
0130 
0131     for (i = 0; i < max_wait; i++) {
0132         v = ioread32(pt3->regs[0] + REG_I2C_R);
0133         if (!(v & STAT_SEQ_RUNNING))
0134             break;
0135         usleep_range(500, 750);
0136     }
0137     if (i >= max_wait)
0138         return -EIO;
0139     if (result)
0140         *result = v;
0141     return 0;
0142 }
0143 
0144 /* send [pre-]translated i2c msgs stored at addr */
0145 static int send_i2c_cmd(struct pt3_board *pt3, u32 addr)
0146 {
0147     u32 ret;
0148 
0149     /* make sure that previous transactions had finished */
0150     if (wait_i2c_result(pt3, NULL, 50)) {
0151         dev_warn(&pt3->pdev->dev, "(%s) prev. transaction stalled\n",
0152                 __func__);
0153         return -EIO;
0154     }
0155 
0156     iowrite32(PT3_I2C_RUN | addr, pt3->regs[0] + REG_I2C_W);
0157     usleep_range(200, 300);
0158     /* wait for the current transaction to finish */
0159     if (wait_i2c_result(pt3, &ret, 500) || (ret & STAT_SEQ_ERROR)) {
0160         dev_warn(&pt3->pdev->dev, "(%s) failed.\n", __func__);
0161         return -EIO;
0162     }
0163     return 0;
0164 }
0165 
0166 
0167 /* init commands for each demod are combined into one transaction
0168  *  and hidden in ROM with the address PT3_CMD_ADDR_INIT_DEMOD.
0169  */
0170 int  pt3_init_all_demods(struct pt3_board *pt3)
0171 {
0172     ioread32(pt3->regs[0] + REG_I2C_R);
0173     return send_i2c_cmd(pt3, PT3_CMD_ADDR_INIT_DEMOD);
0174 }
0175 
0176 /* init commands for two ISDB-T tuners are hidden in ROM. */
0177 int  pt3_init_all_mxl301rf(struct pt3_board *pt3)
0178 {
0179     usleep_range(1000, 2000);
0180     return send_i2c_cmd(pt3, PT3_CMD_ADDR_INIT_TUNER);
0181 }
0182 
0183 void pt3_i2c_reset(struct pt3_board *pt3)
0184 {
0185     iowrite32(PT3_I2C_RESET, pt3->regs[0] + REG_I2C_W);
0186 }
0187 
0188 /*
0189  * I2C algorithm
0190  */
0191 int
0192 pt3_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
0193 {
0194     struct pt3_board *pt3;
0195     struct pt3_i2cbuf *cbuf;
0196     int i;
0197     void __iomem *p;
0198 
0199     pt3 = i2c_get_adapdata(adap);
0200     cbuf = pt3->i2c_buf;
0201 
0202     for (i = 0; i < num; i++)
0203         if (msgs[i].flags & I2C_M_RECV_LEN) {
0204             dev_warn(&pt3->pdev->dev,
0205                 "(%s) I2C_M_RECV_LEN not supported.\n",
0206                 __func__);
0207             return -EINVAL;
0208         }
0209 
0210     translate(cbuf, msgs, num);
0211     memcpy_toio(pt3->regs[1] + PT3_I2C_BASE + PT3_CMD_ADDR_NORMAL / 2,
0212             cbuf->data, cbuf->num_cmds);
0213 
0214     if (send_i2c_cmd(pt3, PT3_CMD_ADDR_NORMAL) < 0)
0215         return -EIO;
0216 
0217     p = pt3->regs[1] + PT3_I2C_BASE;
0218     for (i = 0; i < num; i++)
0219         if ((msgs[i].flags & I2C_M_RD) && msgs[i].len > 0) {
0220             memcpy_fromio(msgs[i].buf, p, msgs[i].len);
0221             p += msgs[i].len;
0222         }
0223 
0224     return num;
0225 }
0226 
0227 u32 pt3_i2c_functionality(struct i2c_adapter *adap)
0228 {
0229     return I2C_FUNC_I2C;
0230 }