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

nv_i2c.c (3787B)


      1/*
      2 * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c
      3 *
      4 * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
      5 *
      6 * Based on rivafb-i2c.c
      7 *
      8 * This file is subject to the terms and conditions of the GNU General Public
      9 * License.  See the file COPYING in the main directory of this archive
     10 * for more details.
     11 */
     12
     13#include <linux/module.h>
     14#include <linux/kernel.h>
     15#include <linux/delay.h>
     16#include <linux/gfp.h>
     17#include <linux/pci.h>
     18#include <linux/fb.h>
     19
     20#include <asm/io.h>
     21
     22#include "nv_type.h"
     23#include "nv_local.h"
     24#include "nv_proto.h"
     25
     26#include "../edid.h"
     27
     28static void nvidia_gpio_setscl(void *data, int state)
     29{
     30	struct nvidia_i2c_chan *chan = data;
     31	struct nvidia_par *par = chan->par;
     32	u32 val;
     33
     34	val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;
     35
     36	if (state)
     37		val |= 0x20;
     38	else
     39		val &= ~0x20;
     40
     41	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
     42}
     43
     44static void nvidia_gpio_setsda(void *data, int state)
     45{
     46	struct nvidia_i2c_chan *chan = data;
     47	struct nvidia_par *par = chan->par;
     48	u32 val;
     49
     50	val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;
     51
     52	if (state)
     53		val |= 0x10;
     54	else
     55		val &= ~0x10;
     56
     57	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
     58}
     59
     60static int nvidia_gpio_getscl(void *data)
     61{
     62	struct nvidia_i2c_chan *chan = data;
     63	struct nvidia_par *par = chan->par;
     64	u32 val = 0;
     65
     66	if (NVReadCrtc(par, chan->ddc_base) & 0x04)
     67		val = 1;
     68
     69	return val;
     70}
     71
     72static int nvidia_gpio_getsda(void *data)
     73{
     74	struct nvidia_i2c_chan *chan = data;
     75	struct nvidia_par *par = chan->par;
     76	u32 val = 0;
     77
     78	if (NVReadCrtc(par, chan->ddc_base) & 0x08)
     79		val = 1;
     80
     81	return val;
     82}
     83
     84static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name,
     85				unsigned int i2c_class)
     86{
     87	int rc;
     88
     89	strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
     90	chan->adapter.owner = THIS_MODULE;
     91	chan->adapter.class = i2c_class;
     92	chan->adapter.algo_data = &chan->algo;
     93	chan->adapter.dev.parent = &chan->par->pci_dev->dev;
     94	chan->algo.setsda = nvidia_gpio_setsda;
     95	chan->algo.setscl = nvidia_gpio_setscl;
     96	chan->algo.getsda = nvidia_gpio_getsda;
     97	chan->algo.getscl = nvidia_gpio_getscl;
     98	chan->algo.udelay = 40;
     99	chan->algo.timeout = msecs_to_jiffies(2);
    100	chan->algo.data = chan;
    101
    102	i2c_set_adapdata(&chan->adapter, chan);
    103
    104	/* Raise SCL and SDA */
    105	nvidia_gpio_setsda(chan, 1);
    106	nvidia_gpio_setscl(chan, 1);
    107	udelay(20);
    108
    109	rc = i2c_bit_add_bus(&chan->adapter);
    110	if (rc == 0)
    111		dev_dbg(&chan->par->pci_dev->dev,
    112			"I2C bus %s registered.\n", name);
    113	else {
    114		dev_warn(&chan->par->pci_dev->dev,
    115			 "Failed to register I2C bus %s.\n", name);
    116		chan->par = NULL;
    117	}
    118
    119	return rc;
    120}
    121
    122void nvidia_create_i2c_busses(struct nvidia_par *par)
    123{
    124	par->chan[0].par = par;
    125	par->chan[1].par = par;
    126	par->chan[2].par = par;
    127
    128	par->chan[0].ddc_base = (par->reverse_i2c) ? 0x36 : 0x3e;
    129 	nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0",
    130			     (par->reverse_i2c) ? I2C_CLASS_HWMON : 0);
    131
    132	par->chan[1].ddc_base = (par->reverse_i2c) ? 0x3e : 0x36;
    133 	nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1",
    134			     (par->reverse_i2c) ? 0 : I2C_CLASS_HWMON);
    135
    136	par->chan[2].ddc_base = 0x50;
    137 	nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0);
    138}
    139
    140void nvidia_delete_i2c_busses(struct nvidia_par *par)
    141{
    142	int i;
    143
    144	for (i = 0; i < 3; i++) {
    145		if (!par->chan[i].par)
    146			continue;
    147		i2c_del_adapter(&par->chan[i].adapter);
    148		par->chan[i].par = NULL;
    149	}
    150}
    151
    152int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
    153{
    154	struct nvidia_par *par = info->par;
    155	u8 *edid = NULL;
    156
    157	if (par->chan[conn - 1].par)
    158		edid = fb_ddc_read(&par->chan[conn - 1].adapter);
    159
    160	if (!edid && conn == 1) {
    161		/* try to get from firmware */
    162		const u8 *e = fb_firmware_edid(info->device);
    163
    164		if (e != NULL)
    165			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
    166	}
    167
    168	*out_edid = edid;
    169
    170	return (edid) ? 0 : 1;
    171}