1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29a0bf528SMauro Carvalho Chehab /*
39a0bf528SMauro Carvalho Chehab  * Allegro A8293 SEC driver
49a0bf528SMauro Carvalho Chehab  *
59a0bf528SMauro Carvalho Chehab  * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
69a0bf528SMauro Carvalho Chehab  */
79a0bf528SMauro Carvalho Chehab 
89a0bf528SMauro Carvalho Chehab #include "a8293.h"
99a0bf528SMauro Carvalho Chehab 
10e6431a0cSChuck Ritola #define A8293_FLAG_ODT			0x10
11e6431a0cSChuck Ritola 
122c509b86SAntti Palosaari struct a8293_dev {
13b561baecSAntti Palosaari 	struct i2c_client *client;
149a0bf528SMauro Carvalho Chehab 	u8 reg[2];
15e6431a0cSChuck Ritola 	int volt_slew_nanos_per_mv;
169a0bf528SMauro Carvalho Chehab };
179a0bf528SMauro Carvalho Chehab 
18e6431a0cSChuck Ritola /*
19e6431a0cSChuck Ritola  * When increasing voltage, do so in minimal steps over time, minimizing
20e6431a0cSChuck Ritola  * risk of vIN undervoltage.
21e6431a0cSChuck Ritola  */
22e6431a0cSChuck Ritola 
a8293_set_voltage_slew(struct a8293_dev * dev,struct i2c_client * client,enum fe_sec_voltage fe_sec_voltage,int min_nanos_per_mv)23e6431a0cSChuck Ritola static int a8293_set_voltage_slew(struct a8293_dev *dev,
24e6431a0cSChuck Ritola 				  struct i2c_client *client,
25e6431a0cSChuck Ritola 				  enum fe_sec_voltage fe_sec_voltage,
26e6431a0cSChuck Ritola 				  int min_nanos_per_mv)
27e6431a0cSChuck Ritola {
28e6431a0cSChuck Ritola 	int ret;
29e6431a0cSChuck Ritola 	u8 reg0, reg1;
30e6431a0cSChuck Ritola 	int new_volt_idx;
31e6431a0cSChuck Ritola 	const int idx_to_mv[] = {
32e6431a0cSChuck Ritola 		0,    12709, 13042, 13375, 14042, 15042, 18042, 18709, 19042
33e6431a0cSChuck Ritola 	};
34e6431a0cSChuck Ritola 	const u8 idx_to_reg[] = {
35e6431a0cSChuck Ritola 		0x00, 0x20,  0x21,  0x22,  0x24,  0x27,  0x28,  0x2A,  0x2B
36e6431a0cSChuck Ritola 	};
37e6431a0cSChuck Ritola 	int this_volt_idx;
38e6431a0cSChuck Ritola 	u8 status;
39e6431a0cSChuck Ritola 	int prev_volt_idx;
40e6431a0cSChuck Ritola 
41e6431a0cSChuck Ritola 	dev_dbg(&client->dev, "set_voltage_slew fe_sec_voltage=%d\n",
42e6431a0cSChuck Ritola 		fe_sec_voltage);
43e6431a0cSChuck Ritola 
44e6431a0cSChuck Ritola 	/* Read status register to clear any stale faults. */
45e6431a0cSChuck Ritola 	ret = i2c_master_recv(client, &status, 1);
46e6431a0cSChuck Ritola 	if (ret < 0)
47e6431a0cSChuck Ritola 		goto err;
48e6431a0cSChuck Ritola 
49e6431a0cSChuck Ritola 	/* Determine previous voltage */
50e6431a0cSChuck Ritola 	switch (dev->reg[0] & 0x2F) {
51e6431a0cSChuck Ritola 	case 0x00:
52e6431a0cSChuck Ritola 		prev_volt_idx = 0;
53e6431a0cSChuck Ritola 		break;
54e6431a0cSChuck Ritola 	case 0x20:
55e6431a0cSChuck Ritola 		prev_volt_idx = 1;
56e6431a0cSChuck Ritola 		break;
57e6431a0cSChuck Ritola 	case 0x21:
58e6431a0cSChuck Ritola 		prev_volt_idx = 2;
59e6431a0cSChuck Ritola 		break;
60e6431a0cSChuck Ritola 	case 0x22:
61e6431a0cSChuck Ritola 		prev_volt_idx = 3;
62e6431a0cSChuck Ritola 		break;
63e6431a0cSChuck Ritola 	case 0x24:
64e6431a0cSChuck Ritola 		prev_volt_idx = 4;
65e6431a0cSChuck Ritola 		break;
66e6431a0cSChuck Ritola 	case 0x27:
67e6431a0cSChuck Ritola 		prev_volt_idx = 5;
68e6431a0cSChuck Ritola 		break;
69e6431a0cSChuck Ritola 	case 0x28:
70e6431a0cSChuck Ritola 		prev_volt_idx = 6;
71e6431a0cSChuck Ritola 		break;
72e6431a0cSChuck Ritola 	case 0x2A:
73e6431a0cSChuck Ritola 		prev_volt_idx = 7;
74e6431a0cSChuck Ritola 		break;
75e6431a0cSChuck Ritola 	case 0x2B:
76e6431a0cSChuck Ritola 		prev_volt_idx = 8;
77e6431a0cSChuck Ritola 		break;
78e6431a0cSChuck Ritola 	default:
79e6431a0cSChuck Ritola 		prev_volt_idx = 0;
80e6431a0cSChuck Ritola 	}
81e6431a0cSChuck Ritola 
82e6431a0cSChuck Ritola 	/* Determine new voltage */
83e6431a0cSChuck Ritola 	switch (fe_sec_voltage) {
84e6431a0cSChuck Ritola 	case SEC_VOLTAGE_OFF:
85e6431a0cSChuck Ritola 		new_volt_idx = 0;
86e6431a0cSChuck Ritola 		break;
87e6431a0cSChuck Ritola 	case SEC_VOLTAGE_13:
88e6431a0cSChuck Ritola 		new_volt_idx = 2;
89e6431a0cSChuck Ritola 		break;
90e6431a0cSChuck Ritola 	case SEC_VOLTAGE_18:
91e6431a0cSChuck Ritola 		new_volt_idx = 6;
92e6431a0cSChuck Ritola 		break;
93e6431a0cSChuck Ritola 	default:
94e6431a0cSChuck Ritola 		ret = -EINVAL;
95e6431a0cSChuck Ritola 		goto err;
96e6431a0cSChuck Ritola 	}
97e6431a0cSChuck Ritola 
98e6431a0cSChuck Ritola 	/* Slew to new voltage if new voltage is greater than current voltage */
99e6431a0cSChuck Ritola 	this_volt_idx = prev_volt_idx;
100e6431a0cSChuck Ritola 	if (this_volt_idx < new_volt_idx) {
101e6431a0cSChuck Ritola 		while (this_volt_idx < new_volt_idx) {
102e6431a0cSChuck Ritola 			int delta_mv = idx_to_mv[this_volt_idx+1] - idx_to_mv[this_volt_idx];
103e6431a0cSChuck Ritola 			int min_wait_time = delta_mv * min_nanos_per_mv;
104e6431a0cSChuck Ritola 
105e6431a0cSChuck Ritola 			reg0 = idx_to_reg[this_volt_idx+1];
106e6431a0cSChuck Ritola 			reg0 |= A8293_FLAG_ODT;
107e6431a0cSChuck Ritola 
108e6431a0cSChuck Ritola 			ret = i2c_master_send(client, &reg0, 1);
109e6431a0cSChuck Ritola 			if (ret < 0)
110e6431a0cSChuck Ritola 				goto err;
111e6431a0cSChuck Ritola 			dev->reg[0] = reg0;
112e6431a0cSChuck Ritola 			this_volt_idx++;
113e6431a0cSChuck Ritola 			usleep_range(min_wait_time, min_wait_time * 2);
114e6431a0cSChuck Ritola 		}
115e6431a0cSChuck Ritola 	} else { /* Else just set the voltage */
116e6431a0cSChuck Ritola 		reg0 = idx_to_reg[new_volt_idx];
117e6431a0cSChuck Ritola 		reg0 |= A8293_FLAG_ODT;
118e6431a0cSChuck Ritola 		ret = i2c_master_send(client, &reg0, 1);
119e6431a0cSChuck Ritola 		if (ret < 0)
120e6431a0cSChuck Ritola 			goto err;
121e6431a0cSChuck Ritola 		dev->reg[0] = reg0;
122e6431a0cSChuck Ritola 	}
123e6431a0cSChuck Ritola 
124e6431a0cSChuck Ritola 	/* TMODE=0, TGATE=1 */
125e6431a0cSChuck Ritola 	reg1 = 0x82;
126e6431a0cSChuck Ritola 	if (reg1 != dev->reg[1]) {
127e6431a0cSChuck Ritola 		ret = i2c_master_send(client, &reg1, 1);
128e6431a0cSChuck Ritola 		if (ret < 0)
129e6431a0cSChuck Ritola 			goto err;
130e6431a0cSChuck Ritola 		dev->reg[1] = reg1;
131e6431a0cSChuck Ritola 	}
132e6431a0cSChuck Ritola 
133e6431a0cSChuck Ritola 	usleep_range(1500, 5000);
134e6431a0cSChuck Ritola 
135e6431a0cSChuck Ritola 	return 0;
136e6431a0cSChuck Ritola err:
137e6431a0cSChuck Ritola 	dev_dbg(&client->dev, "failed=%d\n", ret);
138e6431a0cSChuck Ritola 	return ret;
139e6431a0cSChuck Ritola }
140e6431a0cSChuck Ritola 
141e6431a0cSChuck Ritola 
a8293_set_voltage_noslew(struct dvb_frontend * fe,enum fe_sec_voltage fe_sec_voltage)142e6431a0cSChuck Ritola static int a8293_set_voltage_noslew(struct dvb_frontend *fe,
1430df289a2SMauro Carvalho Chehab 				    enum fe_sec_voltage fe_sec_voltage)
1449a0bf528SMauro Carvalho Chehab {
1452c509b86SAntti Palosaari 	struct a8293_dev *dev = fe->sec_priv;
1462c509b86SAntti Palosaari 	struct i2c_client *client = dev->client;
1479a0bf528SMauro Carvalho Chehab 	int ret;
1484bef67e3SAntti Palosaari 	u8 reg0, reg1;
1499a0bf528SMauro Carvalho Chehab 
150e6431a0cSChuck Ritola 	dev_dbg(&client->dev, "set_voltage_noslew fe_sec_voltage=%d\n",
151e6431a0cSChuck Ritola 		fe_sec_voltage);
1529a0bf528SMauro Carvalho Chehab 
1539a0bf528SMauro Carvalho Chehab 	switch (fe_sec_voltage) {
1549a0bf528SMauro Carvalho Chehab 	case SEC_VOLTAGE_OFF:
1559a0bf528SMauro Carvalho Chehab 		/* ENB=0 */
1564bef67e3SAntti Palosaari 		reg0 = 0x10;
1579a0bf528SMauro Carvalho Chehab 		break;
1589a0bf528SMauro Carvalho Chehab 	case SEC_VOLTAGE_13:
1599a0bf528SMauro Carvalho Chehab 		/* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
1604bef67e3SAntti Palosaari 		reg0 = 0x31;
1619a0bf528SMauro Carvalho Chehab 		break;
1629a0bf528SMauro Carvalho Chehab 	case SEC_VOLTAGE_18:
1639a0bf528SMauro Carvalho Chehab 		/* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
1644bef67e3SAntti Palosaari 		reg0 = 0x38;
1659a0bf528SMauro Carvalho Chehab 		break;
1669a0bf528SMauro Carvalho Chehab 	default:
1679a0bf528SMauro Carvalho Chehab 		ret = -EINVAL;
1689a0bf528SMauro Carvalho Chehab 		goto err;
169c2c1b415SPeter Senna Tschudin 	}
1704bef67e3SAntti Palosaari 	if (reg0 != dev->reg[0]) {
1714bef67e3SAntti Palosaari 		ret = i2c_master_send(client, &reg0, 1);
1722c509b86SAntti Palosaari 		if (ret < 0)
1739a0bf528SMauro Carvalho Chehab 			goto err;
1744bef67e3SAntti Palosaari 		dev->reg[0] = reg0;
1754bef67e3SAntti Palosaari 	}
1764bef67e3SAntti Palosaari 
1774bef67e3SAntti Palosaari 	/* TMODE=0, TGATE=1 */
1784bef67e3SAntti Palosaari 	reg1 = 0x82;
1794bef67e3SAntti Palosaari 	if (reg1 != dev->reg[1]) {
1804bef67e3SAntti Palosaari 		ret = i2c_master_send(client, &reg1, 1);
1814bef67e3SAntti Palosaari 		if (ret < 0)
1824bef67e3SAntti Palosaari 			goto err;
1834bef67e3SAntti Palosaari 		dev->reg[1] = reg1;
1844bef67e3SAntti Palosaari 	}
1859a0bf528SMauro Carvalho Chehab 
186c0ec1c4dSAntti Palosaari 	usleep_range(1500, 50000);
1872c509b86SAntti Palosaari 	return 0;
1889a0bf528SMauro Carvalho Chehab err:
1892c509b86SAntti Palosaari 	dev_dbg(&client->dev, "failed=%d\n", ret);
1909a0bf528SMauro Carvalho Chehab 	return ret;
1919a0bf528SMauro Carvalho Chehab }
1929a0bf528SMauro Carvalho Chehab 
a8293_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage fe_sec_voltage)193e6431a0cSChuck Ritola static int a8293_set_voltage(struct dvb_frontend *fe,
194e6431a0cSChuck Ritola 			     enum fe_sec_voltage fe_sec_voltage)
195e6431a0cSChuck Ritola {
196e6431a0cSChuck Ritola 	struct a8293_dev *dev = fe->sec_priv;
197e6431a0cSChuck Ritola 	struct i2c_client *client = dev->client;
198e6431a0cSChuck Ritola 	int volt_slew_nanos_per_mv = dev->volt_slew_nanos_per_mv;
199e6431a0cSChuck Ritola 
200e6431a0cSChuck Ritola 	dev_dbg(&client->dev, "set_voltage volt_slew_nanos_per_mv=%d\n",
201e6431a0cSChuck Ritola 		volt_slew_nanos_per_mv);
202e6431a0cSChuck Ritola 
203e6431a0cSChuck Ritola 	/* Use slew version if slew rate is set to a sane value */
204e6431a0cSChuck Ritola 	if (volt_slew_nanos_per_mv > 0 && volt_slew_nanos_per_mv < 1600)
205e6431a0cSChuck Ritola 		a8293_set_voltage_slew(dev, client, fe_sec_voltage,
206e6431a0cSChuck Ritola 				       volt_slew_nanos_per_mv);
207e6431a0cSChuck Ritola 	else
208e6431a0cSChuck Ritola 		a8293_set_voltage_noslew(fe, fe_sec_voltage);
209e6431a0cSChuck Ritola 
210e6431a0cSChuck Ritola 	return 0;
211e6431a0cSChuck Ritola }
212e6431a0cSChuck Ritola 
a8293_probe(struct i2c_client * client)2136266daa6SUwe Kleine-König static int a8293_probe(struct i2c_client *client)
214b561baecSAntti Palosaari {
2152c509b86SAntti Palosaari 	struct a8293_dev *dev;
216b561baecSAntti Palosaari 	struct a8293_platform_data *pdata = client->dev.platform_data;
217b561baecSAntti Palosaari 	struct dvb_frontend *fe = pdata->dvb_frontend;
218b561baecSAntti Palosaari 	int ret;
219b561baecSAntti Palosaari 	u8 buf[2];
220b561baecSAntti Palosaari 
221b561baecSAntti Palosaari 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
222b561baecSAntti Palosaari 	if (!dev) {
223b561baecSAntti Palosaari 		ret = -ENOMEM;
224b561baecSAntti Palosaari 		goto err;
225b561baecSAntti Palosaari 	}
226b561baecSAntti Palosaari 
227b561baecSAntti Palosaari 	dev->client = client;
228e6431a0cSChuck Ritola 	dev->volt_slew_nanos_per_mv = pdata->volt_slew_nanos_per_mv;
229b561baecSAntti Palosaari 
230b561baecSAntti Palosaari 	/* check if the SEC is there */
2312c509b86SAntti Palosaari 	ret = i2c_master_recv(client, buf, 2);
2322c509b86SAntti Palosaari 	if (ret < 0)
233b561baecSAntti Palosaari 		goto err_kfree;
234b561baecSAntti Palosaari 
235b561baecSAntti Palosaari 	/* override frontend ops */
236b561baecSAntti Palosaari 	fe->ops.set_voltage = a8293_set_voltage;
237b561baecSAntti Palosaari 	fe->sec_priv = dev;
238b561baecSAntti Palosaari 	i2c_set_clientdata(client, dev);
239b561baecSAntti Palosaari 
240b561baecSAntti Palosaari 	dev_info(&client->dev, "Allegro A8293 SEC successfully attached\n");
241b561baecSAntti Palosaari 	return 0;
242b561baecSAntti Palosaari err_kfree:
243b561baecSAntti Palosaari 	kfree(dev);
244b561baecSAntti Palosaari err:
245b561baecSAntti Palosaari 	dev_dbg(&client->dev, "failed=%d\n", ret);
246b561baecSAntti Palosaari 	return ret;
247b561baecSAntti Palosaari }
248b561baecSAntti Palosaari 
a8293_remove(struct i2c_client * client)249ed5c2f5fSUwe Kleine-König static void a8293_remove(struct i2c_client *client)
250b561baecSAntti Palosaari {
251b561baecSAntti Palosaari 	struct a8293_dev *dev = i2c_get_clientdata(client);
252b561baecSAntti Palosaari 
253b561baecSAntti Palosaari 	dev_dbg(&client->dev, "\n");
254b561baecSAntti Palosaari 
255b561baecSAntti Palosaari 	kfree(dev);
256b561baecSAntti Palosaari }
257b561baecSAntti Palosaari 
258b561baecSAntti Palosaari static const struct i2c_device_id a8293_id_table[] = {
259b561baecSAntti Palosaari 	{"a8293", 0},
260b561baecSAntti Palosaari 	{}
261b561baecSAntti Palosaari };
262b561baecSAntti Palosaari MODULE_DEVICE_TABLE(i2c, a8293_id_table);
263b561baecSAntti Palosaari 
264b561baecSAntti Palosaari static struct i2c_driver a8293_driver = {
265b561baecSAntti Palosaari 	.driver = {
266b561baecSAntti Palosaari 		.name	= "a8293",
267b561baecSAntti Palosaari 		.suppress_bind_attrs = true,
268b561baecSAntti Palosaari 	},
269*aaeb31c0SUwe Kleine-König 	.probe		= a8293_probe,
270b561baecSAntti Palosaari 	.remove		= a8293_remove,
271b561baecSAntti Palosaari 	.id_table	= a8293_id_table,
272b561baecSAntti Palosaari };
273b561baecSAntti Palosaari 
274b561baecSAntti Palosaari module_i2c_driver(a8293_driver);
275b561baecSAntti Palosaari 
2769a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
2779a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("Allegro A8293 SEC driver");
2789a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL");
279