1/* 2 * Earthsoft PT3 driver 3 * 4 * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation version 2. 9 * 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16#include <linux/delay.h> 17#include <linux/device.h> 18#include <linux/i2c.h> 19#include <linux/io.h> 20#include <linux/pci.h> 21 22#include "pt3.h" 23 24#define PT3_I2C_BASE 2048 25#define PT3_CMD_ADDR_NORMAL 0 26#define PT3_CMD_ADDR_INIT_DEMOD 4096 27#define PT3_CMD_ADDR_INIT_TUNER (4096 + 2042) 28 29/* masks for I2C status register */ 30#define STAT_SEQ_RUNNING 0x1 31#define STAT_SEQ_ERROR 0x6 32#define STAT_NO_SEQ 0x8 33 34#define PT3_I2C_RUN (1 << 16) 35#define PT3_I2C_RESET (1 << 17) 36 37enum ctl_cmd { 38 I_END, 39 I_ADDRESS, 40 I_CLOCK_L, 41 I_CLOCK_H, 42 I_DATA_L, 43 I_DATA_H, 44 I_RESET, 45 I_SLEEP, 46 I_DATA_L_NOP = 0x08, 47 I_DATA_H_NOP = 0x0c, 48 I_DATA_H_READ = 0x0d, 49 I_DATA_H_ACK0 = 0x0e, 50 I_DATA_H_ACK1 = 0x0f, 51}; 52 53 54static void cmdbuf_add(struct pt3_i2cbuf *cbuf, enum ctl_cmd cmd) 55{ 56 int buf_idx; 57 58 if ((cbuf->num_cmds % 2) == 0) 59 cbuf->tmp = cmd; 60 else { 61 cbuf->tmp |= cmd << 4; 62 buf_idx = cbuf->num_cmds / 2; 63 if (buf_idx < ARRAY_SIZE(cbuf->data)) 64 cbuf->data[buf_idx] = cbuf->tmp; 65 } 66 cbuf->num_cmds++; 67} 68 69static void put_end(struct pt3_i2cbuf *cbuf) 70{ 71 cmdbuf_add(cbuf, I_END); 72 if (cbuf->num_cmds % 2) 73 cmdbuf_add(cbuf, I_END); 74} 75 76static void put_start(struct pt3_i2cbuf *cbuf) 77{ 78 cmdbuf_add(cbuf, I_DATA_H); 79 cmdbuf_add(cbuf, I_CLOCK_H); 80 cmdbuf_add(cbuf, I_DATA_L); 81 cmdbuf_add(cbuf, I_CLOCK_L); 82} 83 84static void put_byte_write(struct pt3_i2cbuf *cbuf, u8 val) 85{ 86 u8 mask; 87 88 mask = 0x80; 89 for (mask = 0x80; mask > 0; mask >>= 1) 90 cmdbuf_add(cbuf, (val & mask) ? I_DATA_H_NOP : I_DATA_L_NOP); 91 cmdbuf_add(cbuf, I_DATA_H_ACK0); 92} 93 94static void put_byte_read(struct pt3_i2cbuf *cbuf, u32 size) 95{ 96 int i, j; 97 98 for (i = 0; i < size; i++) { 99 for (j = 0; j < 8; j++) 100 cmdbuf_add(cbuf, I_DATA_H_READ); 101 cmdbuf_add(cbuf, (i == size - 1) ? I_DATA_H_NOP : I_DATA_L_NOP); 102 } 103} 104 105static void put_stop(struct pt3_i2cbuf *cbuf) 106{ 107 cmdbuf_add(cbuf, I_DATA_L); 108 cmdbuf_add(cbuf, I_CLOCK_H); 109 cmdbuf_add(cbuf, I_DATA_H); 110} 111 112 113/* translates msgs to internal commands for bit-banging */ 114static void translate(struct pt3_i2cbuf *cbuf, struct i2c_msg *msgs, int num) 115{ 116 int i, j; 117 bool rd; 118 119 cbuf->num_cmds = 0; 120 for (i = 0; i < num; i++) { 121 rd = !!(msgs[i].flags & I2C_M_RD); 122 put_start(cbuf); 123 put_byte_write(cbuf, msgs[i].addr << 1 | rd); 124 if (rd) 125 put_byte_read(cbuf, msgs[i].len); 126 else 127 for (j = 0; j < msgs[i].len; j++) 128 put_byte_write(cbuf, msgs[i].buf[j]); 129 } 130 if (num > 0) { 131 put_stop(cbuf); 132 put_end(cbuf); 133 } 134} 135 136static int wait_i2c_result(struct pt3_board *pt3, u32 *result, int max_wait) 137{ 138 int i; 139 u32 v; 140 141 for (i = 0; i < max_wait; i++) { 142 v = ioread32(pt3->regs[0] + REG_I2C_R); 143 if (!(v & STAT_SEQ_RUNNING)) 144 break; 145 usleep_range(500, 750); 146 } 147 if (i >= max_wait) 148 return -EIO; 149 if (result) 150 *result = v; 151 return 0; 152} 153 154/* send [pre-]translated i2c msgs stored at addr */ 155static int send_i2c_cmd(struct pt3_board *pt3, u32 addr) 156{ 157 u32 ret; 158 159 /* make sure that previous transactions had finished */ 160 if (wait_i2c_result(pt3, NULL, 50)) { 161 dev_warn(&pt3->pdev->dev, "(%s) prev. transaction stalled\n", 162 __func__); 163 return -EIO; 164 } 165 166 iowrite32(PT3_I2C_RUN | addr, pt3->regs[0] + REG_I2C_W); 167 usleep_range(200, 300); 168 /* wait for the current transaction to finish */ 169 if (wait_i2c_result(pt3, &ret, 500) || (ret & STAT_SEQ_ERROR)) { 170 dev_warn(&pt3->pdev->dev, "(%s) failed.\n", __func__); 171 return -EIO; 172 } 173 return 0; 174} 175 176 177/* init commands for each demod are combined into one transaction 178 * and hidden in ROM with the address PT3_CMD_ADDR_INIT_DEMOD. 179 */ 180int pt3_init_all_demods(struct pt3_board *pt3) 181{ 182 ioread32(pt3->regs[0] + REG_I2C_R); 183 return send_i2c_cmd(pt3, PT3_CMD_ADDR_INIT_DEMOD); 184} 185 186/* init commands for two ISDB-T tuners are hidden in ROM. */ 187int pt3_init_all_mxl301rf(struct pt3_board *pt3) 188{ 189 usleep_range(1000, 2000); 190 return send_i2c_cmd(pt3, PT3_CMD_ADDR_INIT_TUNER); 191} 192 193void pt3_i2c_reset(struct pt3_board *pt3) 194{ 195 iowrite32(PT3_I2C_RESET, pt3->regs[0] + REG_I2C_W); 196} 197 198/* 199 * I2C algorithm 200 */ 201int 202pt3_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 203{ 204 struct pt3_board *pt3; 205 struct pt3_i2cbuf *cbuf; 206 int i; 207 void __iomem *p; 208 209 pt3 = i2c_get_adapdata(adap); 210 cbuf = pt3->i2c_buf; 211 212 for (i = 0; i < num; i++) 213 if (msgs[i].flags & I2C_M_RECV_LEN) { 214 dev_warn(&pt3->pdev->dev, 215 "(%s) I2C_M_RECV_LEN not supported.\n", 216 __func__); 217 return -EINVAL; 218 } 219 220 translate(cbuf, msgs, num); 221 memcpy_toio(pt3->regs[1] + PT3_I2C_BASE + PT3_CMD_ADDR_NORMAL / 2, 222 cbuf->data, cbuf->num_cmds); 223 224 if (send_i2c_cmd(pt3, PT3_CMD_ADDR_NORMAL) < 0) 225 return -EIO; 226 227 p = pt3->regs[1] + PT3_I2C_BASE; 228 for (i = 0; i < num; i++) 229 if ((msgs[i].flags & I2C_M_RD) && msgs[i].len > 0) { 230 memcpy_fromio(msgs[i].buf, p, msgs[i].len); 231 p += msgs[i].len; 232 } 233 234 return num; 235} 236 237u32 pt3_i2c_functionality(struct i2c_adapter *adap) 238{ 239 return I2C_FUNC_I2C; 240} 241