cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

isl6423.c (6025B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3	Intersil ISL6423 SEC and LNB Power supply controller
      4
      5	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
      6
      7*/
      8
      9#include <linux/delay.h>
     10#include <linux/errno.h>
     11#include <linux/init.h>
     12#include <linux/kernel.h>
     13#include <linux/module.h>
     14#include <linux/string.h>
     15#include <linux/slab.h>
     16
     17#include <media/dvb_frontend.h>
     18#include "isl6423.h"
     19
     20static unsigned int verbose;
     21module_param(verbose, int, 0644);
     22MODULE_PARM_DESC(verbose, "Set Verbosity level");
     23
     24#define FE_ERROR				0
     25#define FE_NOTICE				1
     26#define FE_INFO					2
     27#define FE_DEBUG				3
     28#define FE_DEBUGREG				4
     29
     30#define dprintk(__y, __z, format, arg...) do {						\
     31	if (__z) {									\
     32		if	((verbose > FE_ERROR) && (verbose > __y))			\
     33			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
     34		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
     35			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
     36		else if ((verbose > FE_INFO) && (verbose > __y))			\
     37			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
     38		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
     39			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
     40	} else {									\
     41		if (verbose > __y)							\
     42			printk(format, ##arg);						\
     43	}										\
     44} while (0)
     45
     46struct isl6423_dev {
     47	const struct isl6423_config	*config;
     48	struct i2c_adapter		*i2c;
     49
     50	u8 reg_3;
     51	u8 reg_4;
     52
     53	unsigned int verbose;
     54};
     55
     56static int isl6423_write(struct isl6423_dev *isl6423, u8 reg)
     57{
     58	struct i2c_adapter *i2c = isl6423->i2c;
     59	u8 addr			= isl6423->config->addr;
     60	int err = 0;
     61
     62	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = &reg, .len = 1 };
     63
     64	dprintk(FE_DEBUG, 1, "write reg %02X", reg);
     65	err = i2c_transfer(i2c, &msg, 1);
     66	if (err < 0)
     67		goto exit;
     68	return 0;
     69
     70exit:
     71	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
     72	return err;
     73}
     74
     75static int isl6423_set_modulation(struct dvb_frontend *fe)
     76{
     77	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;
     78	const struct isl6423_config *config	= isl6423->config;
     79	int err = 0;
     80	u8 reg_2 = 0;
     81
     82	reg_2 = 0x01 << 5;
     83
     84	if (config->mod_extern)
     85		reg_2 |= (1 << 3);
     86	else
     87		reg_2 |= (1 << 4);
     88
     89	err = isl6423_write(isl6423, reg_2);
     90	if (err < 0)
     91		goto exit;
     92	return 0;
     93
     94exit:
     95	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
     96	return err;
     97}
     98
     99static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg)
    100{
    101	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
    102	u8 reg_3 = isl6423->reg_3;
    103	u8 reg_4 = isl6423->reg_4;
    104	int err = 0;
    105
    106	if (arg) {
    107		/* EN = 1, VSPEN = 1, VBOT = 1 */
    108		reg_4 |= (1 << 4);
    109		reg_4 |= 0x1;
    110		reg_3 |= (1 << 3);
    111	} else {
    112		/* EN = 1, VSPEN = 1, VBOT = 0 */
    113		reg_4 |= (1 << 4);
    114		reg_4 &= ~0x1;
    115		reg_3 |= (1 << 3);
    116	}
    117	err = isl6423_write(isl6423, reg_3);
    118	if (err < 0)
    119		goto exit;
    120
    121	err = isl6423_write(isl6423, reg_4);
    122	if (err < 0)
    123		goto exit;
    124
    125	isl6423->reg_3 = reg_3;
    126	isl6423->reg_4 = reg_4;
    127
    128	return 0;
    129exit:
    130	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
    131	return err;
    132}
    133
    134
    135static int isl6423_set_voltage(struct dvb_frontend *fe,
    136			       enum fe_sec_voltage voltage)
    137{
    138	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
    139	u8 reg_3 = isl6423->reg_3;
    140	u8 reg_4 = isl6423->reg_4;
    141	int err = 0;
    142
    143	switch (voltage) {
    144	case SEC_VOLTAGE_OFF:
    145		/* EN = 0 */
    146		reg_4 &= ~(1 << 4);
    147		break;
    148
    149	case SEC_VOLTAGE_13:
    150		/* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */
    151		reg_4 |= (1 << 4);
    152		reg_4 &= ~0x3;
    153		reg_3 |= (1 << 3);
    154		break;
    155
    156	case SEC_VOLTAGE_18:
    157		/* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */
    158		reg_4 |= (1 << 4);
    159		reg_4 |=  0x2;
    160		reg_4 &= ~0x1;
    161		reg_3 |= (1 << 3);
    162		break;
    163
    164	default:
    165		break;
    166	}
    167	err = isl6423_write(isl6423, reg_3);
    168	if (err < 0)
    169		goto exit;
    170
    171	err = isl6423_write(isl6423, reg_4);
    172	if (err < 0)
    173		goto exit;
    174
    175	isl6423->reg_3 = reg_3;
    176	isl6423->reg_4 = reg_4;
    177
    178	return 0;
    179exit:
    180	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
    181	return err;
    182}
    183
    184static int isl6423_set_current(struct dvb_frontend *fe)
    185{
    186	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;
    187	u8 reg_3 = isl6423->reg_3;
    188	const struct isl6423_config *config	= isl6423->config;
    189	int err = 0;
    190
    191	switch (config->current_max) {
    192	case SEC_CURRENT_275m:
    193		/* 275mA */
    194		/* ISELH = 0, ISELL = 0 */
    195		reg_3 &= ~0x3;
    196		break;
    197
    198	case SEC_CURRENT_515m:
    199		/* 515mA */
    200		/* ISELH = 0, ISELL = 1 */
    201		reg_3 &= ~0x2;
    202		reg_3 |=  0x1;
    203		break;
    204
    205	case SEC_CURRENT_635m:
    206		/* 635mA */
    207		/* ISELH = 1, ISELL = 0 */
    208		reg_3 &= ~0x1;
    209		reg_3 |=  0x2;
    210		break;
    211
    212	case SEC_CURRENT_800m:
    213		/* 800mA */
    214		/* ISELH = 1, ISELL = 1 */
    215		reg_3 |= 0x3;
    216		break;
    217	}
    218
    219	err = isl6423_write(isl6423, reg_3);
    220	if (err < 0)
    221		goto exit;
    222
    223	switch (config->curlim) {
    224	case SEC_CURRENT_LIM_ON:
    225		/* DCL = 0 */
    226		reg_3 &= ~0x10;
    227		break;
    228
    229	case SEC_CURRENT_LIM_OFF:
    230		/* DCL = 1 */
    231		reg_3 |= 0x10;
    232		break;
    233	}
    234
    235	err = isl6423_write(isl6423, reg_3);
    236	if (err < 0)
    237		goto exit;
    238
    239	isl6423->reg_3 = reg_3;
    240
    241	return 0;
    242exit:
    243	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
    244	return err;
    245}
    246
    247static void isl6423_release(struct dvb_frontend *fe)
    248{
    249	isl6423_set_voltage(fe, SEC_VOLTAGE_OFF);
    250
    251	kfree(fe->sec_priv);
    252	fe->sec_priv = NULL;
    253}
    254
    255struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
    256				    struct i2c_adapter *i2c,
    257				    const struct isl6423_config *config)
    258{
    259	struct isl6423_dev *isl6423;
    260
    261	isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL);
    262	if (!isl6423)
    263		return NULL;
    264
    265	isl6423->config	= config;
    266	isl6423->i2c	= i2c;
    267	fe->sec_priv	= isl6423;
    268
    269	/* SR3H = 0, SR3M = 1, SR3L = 0 */
    270	isl6423->reg_3 = 0x02 << 5;
    271	/* SR4H = 0, SR4M = 1, SR4L = 1 */
    272	isl6423->reg_4 = 0x03 << 5;
    273
    274	if (isl6423_set_current(fe))
    275		goto exit;
    276
    277	if (isl6423_set_modulation(fe))
    278		goto exit;
    279
    280	fe->ops.release_sec		= isl6423_release;
    281	fe->ops.set_voltage		= isl6423_set_voltage;
    282	fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost;
    283	isl6423->verbose		= verbose;
    284
    285	return fe;
    286
    287exit:
    288	kfree(isl6423);
    289	fe->sec_priv = NULL;
    290	return NULL;
    291}
    292EXPORT_SYMBOL(isl6423_attach);
    293
    294MODULE_DESCRIPTION("ISL6423 SEC");
    295MODULE_AUTHOR("Manu Abraham");
    296MODULE_LICENSE("GPL");