xref: /openbmc/linux/drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1  /*
2   * Copyright (c) 2002-2010, Intel Corporation.
3   * Copyright (c) 2014 ATRON electronic GmbH
4   *   Author: Jan Safrata <jan.nikitenko@gmail.com>
5   *
6   * Permission is hereby granted, free of charge, to any person obtaining a copy
7   * of this software and associated documentation files (the "Software"), to deal
8   * in the Software without restriction, including without limitation the rights
9   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10   * copies of the Software, and to permit persons to whom the Software is
11   * furnished to do so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in
14   * all copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22   * THE SOFTWARE.
23   *
24   */
25  
26  #include <linux/delay.h>
27  #include <linux/i2c-algo-bit.h>
28  #include <linux/i2c.h>
29  #include <linux/init.h>
30  #include <linux/io.h>
31  #include <linux/kernel.h>
32  #include <linux/module.h>
33  #include <linux/pci.h>
34  #include <linux/types.h>
35  
36  #include "psb_drv.h"
37  #include "psb_intel_reg.h"
38  
39  
40  /*
41   * LPC GPIO based I2C bus for LVDS of Atom E6xx
42   */
43  
44  /*-----------------------------------------------------------------------------
45   * LPC Register Offsets. Used for LVDS GPIO Bit Bashing. Registers are part
46   * Atom E6xx [D31:F0]
47   ----------------------------------------------------------------------------*/
48  #define RGEN    0x20
49  #define RGIO    0x24
50  #define RGLVL   0x28
51  #define RGTPE   0x2C
52  #define RGTNE   0x30
53  #define RGGPE   0x34
54  #define RGSMI   0x38
55  #define RGTS    0x3C
56  
57  /* The LVDS GPIO clock lines are GPIOSUS[3]
58   * The LVDS GPIO data lines are GPIOSUS[4]
59   */
60  #define GPIO_CLOCK	0x08
61  #define GPIO_DATA	0x10
62  
63  #define LPC_READ_REG(chan, r) inl((chan)->reg + (r))
64  #define LPC_WRITE_REG(chan, r, val) outl((val), (chan)->reg + (r))
65  
get_clock(void * data)66  static int get_clock(void *data)
67  {
68  	struct gma_i2c_chan *chan = data;
69  	u32 val;
70  
71  	val = LPC_READ_REG(chan, RGIO);
72  	val |= GPIO_CLOCK;
73  	LPC_WRITE_REG(chan, RGIO, val);
74  	LPC_READ_REG(chan, RGLVL);
75  	val = (LPC_READ_REG(chan, RGLVL) & GPIO_CLOCK) ? 1 : 0;
76  
77  	return val;
78  }
79  
get_data(void * data)80  static int get_data(void *data)
81  {
82  	struct gma_i2c_chan *chan = data;
83  	u32 val;
84  
85  	val = LPC_READ_REG(chan, RGIO);
86  	val |= GPIO_DATA;
87  	LPC_WRITE_REG(chan, RGIO, val);
88  	LPC_READ_REG(chan, RGLVL);
89  	val = (LPC_READ_REG(chan, RGLVL) & GPIO_DATA) ? 1 : 0;
90  
91  	return val;
92  }
93  
set_clock(void * data,int state_high)94  static void set_clock(void *data, int state_high)
95  {
96  	struct gma_i2c_chan *chan = data;
97  	u32 val;
98  
99  	if (state_high) {
100  		val = LPC_READ_REG(chan, RGIO);
101  		val |= GPIO_CLOCK;
102  		LPC_WRITE_REG(chan, RGIO, val);
103  	} else {
104  		val = LPC_READ_REG(chan, RGIO);
105  		val &= ~GPIO_CLOCK;
106  		LPC_WRITE_REG(chan, RGIO, val);
107  		val = LPC_READ_REG(chan, RGLVL);
108  		val &= ~GPIO_CLOCK;
109  		LPC_WRITE_REG(chan, RGLVL, val);
110  	}
111  }
112  
set_data(void * data,int state_high)113  static void set_data(void *data, int state_high)
114  {
115  	struct gma_i2c_chan *chan = data;
116  	u32 val;
117  
118  	if (state_high) {
119  		val = LPC_READ_REG(chan, RGIO);
120  		val |= GPIO_DATA;
121  		LPC_WRITE_REG(chan, RGIO, val);
122  	} else {
123  		val = LPC_READ_REG(chan, RGIO);
124  		val &= ~GPIO_DATA;
125  		LPC_WRITE_REG(chan, RGIO, val);
126  		val = LPC_READ_REG(chan, RGLVL);
127  		val &= ~GPIO_DATA;
128  		LPC_WRITE_REG(chan, RGLVL, val);
129  	}
130  }
131  
oaktrail_lvds_i2c_init(struct drm_device * dev)132  struct gma_i2c_chan *oaktrail_lvds_i2c_init(struct drm_device *dev)
133  {
134  	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
135  	struct gma_i2c_chan *chan;
136  	int ret;
137  
138  	chan = kzalloc(sizeof(struct gma_i2c_chan), GFP_KERNEL);
139  	if (!chan)
140  		return ERR_PTR(-ENOMEM);
141  
142  	chan->drm_dev = dev;
143  	chan->reg = dev_priv->lpc_gpio_base;
144  	strncpy(chan->base.name, "gma500 LPC",  I2C_NAME_SIZE - 1);
145  	chan->base.owner = THIS_MODULE;
146  	chan->base.algo_data = &chan->algo;
147  	chan->base.dev.parent = dev->dev;
148  	chan->algo.setsda = set_data;
149  	chan->algo.setscl = set_clock;
150  	chan->algo.getsda = get_data;
151  	chan->algo.getscl = get_clock;
152  	chan->algo.udelay = 100;
153  	chan->algo.timeout = usecs_to_jiffies(2200);
154  	chan->algo.data = chan;
155  
156  	i2c_set_adapdata(&chan->base, chan);
157  
158  	set_data(chan, 1);
159  	set_clock(chan, 1);
160  	udelay(50);
161  
162  	ret = i2c_bit_add_bus(&chan->base);
163  	if (ret < 0) {
164  		kfree(chan);
165  		return ERR_PTR(ret);
166  	}
167  
168  	return chan;
169  }
170