summaryrefslogtreecommitdiff
path: root/linux-core/nv50_i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core/nv50_i2c.c')
-rw-r--r--linux-core/nv50_i2c.c400
1 files changed, 0 insertions, 400 deletions
diff --git a/linux-core/nv50_i2c.c b/linux-core/nv50_i2c.c
deleted file mode 100644
index 30e317c5..00000000
--- a/linux-core/nv50_i2c.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (C) 2008 Maarten Maathuis.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-/* This is largely a clone from xorg i2c functions, as i had serious trouble getting an i2c_bit_algo adaptor running. */
-
-#include "nv50_i2c.h"
-
-static uint32_t nv50_i2c_port(int index)
-{
- uint32_t port = 0;
-
- switch (index) {
- case 0:
- port = NV50_PCONNECTOR_I2C_PORT_0;
- break;
- case 1:
- port = NV50_PCONNECTOR_I2C_PORT_1;
- break;
- case 2:
- port = NV50_PCONNECTOR_I2C_PORT_2;
- break;
- case 3:
- port = NV50_PCONNECTOR_I2C_PORT_3;
- break;
- case 4:
- port = NV50_PCONNECTOR_I2C_PORT_4;
- break;
- case 5:
- port = NV50_PCONNECTOR_I2C_PORT_5;
- break;
- default:
- break;
- }
-
- if (!port) {
- DRM_ERROR("Invalid i2c port, returning 0.\n");
- BUG();
- }
-
- return port;
-}
-
-static void nv50_i2c_set_bits(struct nv50_i2c_channel *chan, int clock_high, int data_high)
-{
- struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
- uint32_t port = nv50_i2c_port(chan->index);
-
- if (!port)
- return;
-
- NV_WRITE(port, 4 | (data_high << 1) | clock_high);
-}
-
-static void nv50_i2c_get_bits(struct nv50_i2c_channel *chan, int *clock_high, int *data_high)
-{
- struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
- uint32_t port = nv50_i2c_port(chan->index);
- uint32_t val;
-
- if (!port)
- return;
-
- val = NV_READ(port);
-
- if (val & 1)
- *clock_high = 1;
- else
- *clock_high = 0;
-
- if (val & 2)
- *data_high = 1;
- else
- *data_high = 0;
-}
-
-static bool nv50_i2c_raise_clock(struct nv50_i2c_channel *chan, int data)
-{
- int i, clock;
-
- nv50_i2c_set_bits(chan, 1, data);
- udelay(2);
-
- for (i = 2200; i > 0; i -= 2) {
- nv50_i2c_get_bits(chan, &clock, &data);
- if (clock)
- return true;
- udelay(2);
- }
-
- printk("a timeout occured in nv50_i2c_raise_clock\n");
-
- return false;
-}
-
-static bool nv50_i2c_start(struct nv50_i2c_channel *chan)
-{
- if (!nv50_i2c_raise_clock(chan, 1))
- return false;
-
- nv50_i2c_set_bits(chan, 1, 0);
- udelay(5);
-
- nv50_i2c_set_bits(chan, 0, 0);
- udelay(5);
-
- return true;
-}
-
-static void nv50_i2c_stop(struct nv50_i2c_channel *chan)
-{
- nv50_i2c_set_bits(chan, 0, 0);
- udelay(2);
-
- nv50_i2c_set_bits(chan, 1, 0);
- udelay(5);
-
- nv50_i2c_set_bits(chan, 1, 1);
- udelay(5);
-}
-
-static bool nv50_i2c_write_bit(struct nv50_i2c_channel *chan, int data)
-{
- bool rval;
-
- nv50_i2c_set_bits(chan, 0, data);
- udelay(2);
-
- rval = nv50_i2c_raise_clock(chan, data);
- udelay(5);
-
- nv50_i2c_set_bits(chan, 0, data);
- udelay(5);
-
- return rval;
-}
-
-static bool nv50_i2c_read_bit(struct nv50_i2c_channel *chan, int *data)
-{
- bool rval;
- int clock;
-
- rval = nv50_i2c_raise_clock(chan, 1);
- udelay(5);
-
- nv50_i2c_get_bits(chan, &clock, data);
- udelay(5);
-
- nv50_i2c_set_bits(chan, 0, 1);
- udelay(5);
-
- return rval;
-}
-
-static bool nv50_i2c_write_byte(struct nv50_i2c_channel *chan, uint8_t byte)
-{
- bool rval;
- int i, clock, data;
-
- for (i = 7; i >= 0; i--)
- if (!nv50_i2c_write_bit(chan, (byte >> i) & 1))
- return false;
-
- nv50_i2c_set_bits(chan, 0, 1);
- udelay(5);
-
- rval = nv50_i2c_raise_clock(chan, 1);
-
- if (rval) {
- for (i = 40; i > 0; i -= 2) {
- udelay(2);
- nv50_i2c_get_bits(chan, &clock, &data);
- if (data == 0)
- break;
- }
-
- if (i <= 0) {
- printk("a timeout occured in nv50_i2c_write_byte\n");
- rval = false;
- }
- }
-
- nv50_i2c_set_bits(chan, 0, 1);
- udelay(5);
-
- return rval;
-}
-
-static bool nv50_i2c_read_byte(struct nv50_i2c_channel *chan, uint8_t *byte, bool last)
-{
- int i, bit;
-
- nv50_i2c_set_bits(chan, 0, 1);
- udelay(5);
-
- *byte = 0;
-
- for (i = 7; i >= 0; i--) {
- if (nv50_i2c_read_bit(chan, &bit)) {
- if (bit)
- *byte |= (1 << i);
- } else {
- return false;
- }
- }
-
- if (!nv50_i2c_write_bit(chan, last ? 1 : 0))
- return false;
-
- return true;
-}
-
-/* only 7 bits addresses. */
-static bool nv50_i2c_address(struct nv50_i2c_channel *chan, uint8_t address, bool write)
-{
- if (nv50_i2c_start(chan)) {
- uint8_t real_addr = (address << 1);
- if (!write)
- real_addr |= 1;
-
- if (nv50_i2c_write_byte(chan, real_addr))
- return true;
-
- /* failure, so issue stop */
- nv50_i2c_stop(chan);
- }
-
- return false;
-}
-
-static bool nv50_i2c_read(struct nv50_i2c_channel *chan, uint8_t address, uint8_t *buffer, uint32_t length)
-{
- int i, j;
- bool rval, last;
-
- /* retries */
- for (i = 0; i < 4; i++) {
- rval = nv50_i2c_address(chan, address, false);
- if (!rval)
- return false;
-
- for (j = 0; j < length; j++) {
- last = false;
- if (j == (length - 1))
- last = true;
- rval = nv50_i2c_read_byte(chan, &buffer[j], last);
- if (!rval) {
- nv50_i2c_stop(chan);
- break;
- }
- }
-
- nv50_i2c_stop(chan);
-
- /* done */
- if (rval)
- break;
- }
-
- if (!rval)
- printk("nv50_i2c_read failed\n");
-
- return rval;
-}
-
-static bool nv50_i2c_write(struct nv50_i2c_channel *chan, uint8_t address, uint8_t *buffer, uint32_t length)
-{
- int i, j;
- bool rval;
-
- /* retries */
- for (i = 0; i < 4; i++) {
- rval = nv50_i2c_address(chan, address, true);
- if (!rval)
- return false;
-
- for (j = 0; j < length; j++) {
- rval = nv50_i2c_write_byte(chan, buffer[j]);
- if (!rval) {
- break;
- }
- }
-
- nv50_i2c_stop(chan);
-
- /* done */
- if (rval)
- break;
- }
-
- if (!rval)
- printk("nv50_i2c_write failed\n");
-
- return rval;
-}
-
-static int nv50_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
-{
- struct nv50_i2c_channel *chan = i2c_get_adapdata(i2c_adap);
- bool rval;
- int i;
-
- for (i = 0; i < num; i++) {
- if (msgs[i].flags & I2C_M_RD) { /* read */
- rval = nv50_i2c_read(chan, msgs[i].addr, msgs[i].buf, msgs[i].len);
- } else { /* write */
- rval = nv50_i2c_write(chan, msgs[i].addr, msgs[i].buf, msgs[i].len);
- }
-
- if (!rval)
- break;
- }
-
- if (rval)
- return i;
- else
- return -EINVAL;
-}
-
-static u32 nv50_i2c_functionality(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C;
-}
-
-static const struct i2c_algorithm nv50_i2c_algo = {
- .master_xfer = nv50_i2c_xfer,
- .functionality = nv50_i2c_functionality,
-};
-
-static int nv50_i2c_register_bus(struct i2c_adapter *adap)
-{
- adap->algo = &nv50_i2c_algo;
-
- adap->timeout = 40;
- adap->retries = 4;
-
- return i2c_add_adapter(adap);
-}
-
-#define I2C_HW_B_NOUVEAU 0x010030
-struct nv50_i2c_channel *nv50_i2c_channel_create(struct drm_device *dev, uint32_t index)
-{
- struct nv50_i2c_channel *chan;
-
- chan = kzalloc(sizeof(struct nv50_i2c_channel), GFP_KERNEL);
-
- if (!chan)
- goto out;
-
- DRM_INFO("Creating i2c bus with index %d\n", index);
-
- chan->dev = dev;
- chan->index = index;
- snprintf(chan->adapter.name, I2C_NAME_SIZE, "nv50 i2c %d", index);
- chan->adapter.owner = THIS_MODULE;
- chan->adapter.id = I2C_HW_B_NOUVEAU;
- chan->adapter.dev.parent = &dev->pdev->dev;
-
- i2c_set_adapdata(&chan->adapter, chan);
-
- if (nv50_i2c_register_bus(&chan->adapter))
- goto out;
-
- return chan;
-
-out:
- kfree(chan);
- return NULL;
-}
-
-void nv50_i2c_channel_destroy(struct nv50_i2c_channel *chan)
-{
- if (!chan)
- return;
-
- i2c_del_adapter(&chan->adapter);
- kfree(chan);
-}