162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/powerpc/platforms/powermac/low_i2c.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2003-2005 Ben. Herrenschmidt (benh@kernel.crashing.org)
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * The linux i2c layer isn't completely suitable for our needs for various
862306a36Sopenharmony_ci * reasons ranging from too late initialisation to semantics not perfectly
962306a36Sopenharmony_ci * matching some requirements of the apple platform functions etc...
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * This file thus provides a simple low level unified i2c interface for
1262306a36Sopenharmony_ci * powermac that covers the various types of i2c busses used in Apple machines.
1362306a36Sopenharmony_ci * For now, keywest, PMU and SMU, though we could add Cuda, or other bit
1462306a36Sopenharmony_ci * banging busses found on older chipsets in earlier machines if we ever need
1562306a36Sopenharmony_ci * one of them.
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * The drivers in this file are synchronous/blocking. In addition, the
1862306a36Sopenharmony_ci * keywest one is fairly slow due to the use of msleep instead of interrupts
1962306a36Sopenharmony_ci * as the interrupt is currently used by i2c-keywest. In the long run, we
2062306a36Sopenharmony_ci * might want to get rid of those high-level interfaces to linux i2c layer
2162306a36Sopenharmony_ci * either completely (converting all drivers) or replacing them all with a
2262306a36Sopenharmony_ci * single stub driver on top of this one. Once done, the interrupt will be
2362306a36Sopenharmony_ci * available for our use.
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#undef DEBUG
2762306a36Sopenharmony_ci#undef DEBUG_LOW
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include <linux/types.h>
3062306a36Sopenharmony_ci#include <linux/sched.h>
3162306a36Sopenharmony_ci#include <linux/init.h>
3262306a36Sopenharmony_ci#include <linux/export.h>
3362306a36Sopenharmony_ci#include <linux/adb.h>
3462306a36Sopenharmony_ci#include <linux/pmu.h>
3562306a36Sopenharmony_ci#include <linux/delay.h>
3662306a36Sopenharmony_ci#include <linux/completion.h>
3762306a36Sopenharmony_ci#include <linux/platform_device.h>
3862306a36Sopenharmony_ci#include <linux/interrupt.h>
3962306a36Sopenharmony_ci#include <linux/timer.h>
4062306a36Sopenharmony_ci#include <linux/mutex.h>
4162306a36Sopenharmony_ci#include <linux/i2c.h>
4262306a36Sopenharmony_ci#include <linux/slab.h>
4362306a36Sopenharmony_ci#include <linux/of_irq.h>
4462306a36Sopenharmony_ci#include <asm/keylargo.h>
4562306a36Sopenharmony_ci#include <asm/uninorth.h>
4662306a36Sopenharmony_ci#include <asm/io.h>
4762306a36Sopenharmony_ci#include <asm/machdep.h>
4862306a36Sopenharmony_ci#include <asm/smu.h>
4962306a36Sopenharmony_ci#include <asm/pmac_pfunc.h>
5062306a36Sopenharmony_ci#include <asm/pmac_low_i2c.h>
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#ifdef DEBUG
5362306a36Sopenharmony_ci#define DBG(x...) do {\
5462306a36Sopenharmony_ci		printk(KERN_DEBUG "low_i2c:" x);	\
5562306a36Sopenharmony_ci	} while(0)
5662306a36Sopenharmony_ci#else
5762306a36Sopenharmony_ci#define DBG(x...)
5862306a36Sopenharmony_ci#endif
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#ifdef DEBUG_LOW
6162306a36Sopenharmony_ci#define DBG_LOW(x...) do {\
6262306a36Sopenharmony_ci		printk(KERN_DEBUG "low_i2c:" x);	\
6362306a36Sopenharmony_ci	} while(0)
6462306a36Sopenharmony_ci#else
6562306a36Sopenharmony_ci#define DBG_LOW(x...)
6662306a36Sopenharmony_ci#endif
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic int pmac_i2c_force_poll = 1;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/*
7262306a36Sopenharmony_ci * A bus structure. Each bus in the system has such a structure associated.
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_cistruct pmac_i2c_bus
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	struct list_head	link;
7762306a36Sopenharmony_ci	struct device_node	*controller;
7862306a36Sopenharmony_ci	struct device_node	*busnode;
7962306a36Sopenharmony_ci	int			type;
8062306a36Sopenharmony_ci	int			flags;
8162306a36Sopenharmony_ci	struct i2c_adapter	adapter;
8262306a36Sopenharmony_ci	void			*hostdata;
8362306a36Sopenharmony_ci	int			channel;	/* some hosts have multiple */
8462306a36Sopenharmony_ci	int			mode;		/* current mode */
8562306a36Sopenharmony_ci	struct mutex		mutex;
8662306a36Sopenharmony_ci	int			opened;
8762306a36Sopenharmony_ci	int			polled;		/* open mode */
8862306a36Sopenharmony_ci	struct platform_device	*platform_dev;
8962306a36Sopenharmony_ci	struct lock_class_key   lock_key;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	/* ops */
9262306a36Sopenharmony_ci	int (*open)(struct pmac_i2c_bus *bus);
9362306a36Sopenharmony_ci	void (*close)(struct pmac_i2c_bus *bus);
9462306a36Sopenharmony_ci	int (*xfer)(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
9562306a36Sopenharmony_ci		    u32 subaddr, u8 *data, int len);
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic LIST_HEAD(pmac_i2c_busses);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/*
10162306a36Sopenharmony_ci * Keywest implementation
10262306a36Sopenharmony_ci */
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistruct pmac_i2c_host_kw
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	struct mutex		mutex;		/* Access mutex for use by
10762306a36Sopenharmony_ci						 * i2c-keywest */
10862306a36Sopenharmony_ci	void __iomem		*base;		/* register base address */
10962306a36Sopenharmony_ci	int			bsteps;		/* register stepping */
11062306a36Sopenharmony_ci	int			speed;		/* speed */
11162306a36Sopenharmony_ci	int			irq;
11262306a36Sopenharmony_ci	u8			*data;
11362306a36Sopenharmony_ci	unsigned		len;
11462306a36Sopenharmony_ci	int			state;
11562306a36Sopenharmony_ci	int			rw;
11662306a36Sopenharmony_ci	int			polled;
11762306a36Sopenharmony_ci	int			result;
11862306a36Sopenharmony_ci	struct completion	complete;
11962306a36Sopenharmony_ci	spinlock_t		lock;
12062306a36Sopenharmony_ci	struct timer_list	timeout_timer;
12162306a36Sopenharmony_ci};
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci/* Register indices */
12462306a36Sopenharmony_citypedef enum {
12562306a36Sopenharmony_ci	reg_mode = 0,
12662306a36Sopenharmony_ci	reg_control,
12762306a36Sopenharmony_ci	reg_status,
12862306a36Sopenharmony_ci	reg_isr,
12962306a36Sopenharmony_ci	reg_ier,
13062306a36Sopenharmony_ci	reg_addr,
13162306a36Sopenharmony_ci	reg_subaddr,
13262306a36Sopenharmony_ci	reg_data
13362306a36Sopenharmony_ci} reg_t;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/* The Tumbler audio equalizer can be really slow sometimes */
13662306a36Sopenharmony_ci#define KW_POLL_TIMEOUT		(2*HZ)
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci/* Mode register */
13962306a36Sopenharmony_ci#define KW_I2C_MODE_100KHZ	0x00
14062306a36Sopenharmony_ci#define KW_I2C_MODE_50KHZ	0x01
14162306a36Sopenharmony_ci#define KW_I2C_MODE_25KHZ	0x02
14262306a36Sopenharmony_ci#define KW_I2C_MODE_DUMB	0x00
14362306a36Sopenharmony_ci#define KW_I2C_MODE_STANDARD	0x04
14462306a36Sopenharmony_ci#define KW_I2C_MODE_STANDARDSUB	0x08
14562306a36Sopenharmony_ci#define KW_I2C_MODE_COMBINED	0x0C
14662306a36Sopenharmony_ci#define KW_I2C_MODE_MODE_MASK	0x0C
14762306a36Sopenharmony_ci#define KW_I2C_MODE_CHAN_MASK	0xF0
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/* Control register */
15062306a36Sopenharmony_ci#define KW_I2C_CTL_AAK		0x01
15162306a36Sopenharmony_ci#define KW_I2C_CTL_XADDR	0x02
15262306a36Sopenharmony_ci#define KW_I2C_CTL_STOP		0x04
15362306a36Sopenharmony_ci#define KW_I2C_CTL_START	0x08
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/* Status register */
15662306a36Sopenharmony_ci#define KW_I2C_STAT_BUSY	0x01
15762306a36Sopenharmony_ci#define KW_I2C_STAT_LAST_AAK	0x02
15862306a36Sopenharmony_ci#define KW_I2C_STAT_LAST_RW	0x04
15962306a36Sopenharmony_ci#define KW_I2C_STAT_SDA		0x08
16062306a36Sopenharmony_ci#define KW_I2C_STAT_SCL		0x10
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/* IER & ISR registers */
16362306a36Sopenharmony_ci#define KW_I2C_IRQ_DATA		0x01
16462306a36Sopenharmony_ci#define KW_I2C_IRQ_ADDR		0x02
16562306a36Sopenharmony_ci#define KW_I2C_IRQ_STOP		0x04
16662306a36Sopenharmony_ci#define KW_I2C_IRQ_START	0x08
16762306a36Sopenharmony_ci#define KW_I2C_IRQ_MASK		0x0F
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci/* State machine states */
17062306a36Sopenharmony_cienum {
17162306a36Sopenharmony_ci	state_idle,
17262306a36Sopenharmony_ci	state_addr,
17362306a36Sopenharmony_ci	state_read,
17462306a36Sopenharmony_ci	state_write,
17562306a36Sopenharmony_ci	state_stop,
17662306a36Sopenharmony_ci	state_dead
17762306a36Sopenharmony_ci};
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci#define WRONG_STATE(name) do {\
18062306a36Sopenharmony_ci		printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s " \
18162306a36Sopenharmony_ci		       "(isr: %02x)\n",	\
18262306a36Sopenharmony_ci		       name, __kw_state_names[host->state], isr); \
18362306a36Sopenharmony_ci	} while(0)
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic const char *__kw_state_names[] = {
18662306a36Sopenharmony_ci	"state_idle",
18762306a36Sopenharmony_ci	"state_addr",
18862306a36Sopenharmony_ci	"state_read",
18962306a36Sopenharmony_ci	"state_write",
19062306a36Sopenharmony_ci	"state_stop",
19162306a36Sopenharmony_ci	"state_dead"
19262306a36Sopenharmony_ci};
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic inline u8 __kw_read_reg(struct pmac_i2c_host_kw *host, reg_t reg)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	return readb(host->base + (((unsigned int)reg) << host->bsteps));
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistatic inline void __kw_write_reg(struct pmac_i2c_host_kw *host,
20062306a36Sopenharmony_ci				  reg_t reg, u8 val)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	writeb(val, host->base + (((unsigned)reg) << host->bsteps));
20362306a36Sopenharmony_ci	(void)__kw_read_reg(host, reg_subaddr);
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci#define kw_write_reg(reg, val)	__kw_write_reg(host, reg, val)
20762306a36Sopenharmony_ci#define kw_read_reg(reg)	__kw_read_reg(host, reg)
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic u8 kw_i2c_wait_interrupt(struct pmac_i2c_host_kw *host)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	int i, j;
21262306a36Sopenharmony_ci	u8 isr;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	for (i = 0; i < 1000; i++) {
21562306a36Sopenharmony_ci		isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
21662306a36Sopenharmony_ci		if (isr != 0)
21762306a36Sopenharmony_ci			return isr;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci		/* This code is used with the timebase frozen, we cannot rely
22062306a36Sopenharmony_ci		 * on udelay nor schedule when in polled mode !
22162306a36Sopenharmony_ci		 * For now, just use a bogus loop....
22262306a36Sopenharmony_ci		 */
22362306a36Sopenharmony_ci		if (host->polled) {
22462306a36Sopenharmony_ci			for (j = 1; j < 100000; j++)
22562306a36Sopenharmony_ci				mb();
22662306a36Sopenharmony_ci		} else
22762306a36Sopenharmony_ci			msleep(1);
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci	return isr;
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic void kw_i2c_do_stop(struct pmac_i2c_host_kw *host, int result)
23362306a36Sopenharmony_ci{
23462306a36Sopenharmony_ci	kw_write_reg(reg_control, KW_I2C_CTL_STOP);
23562306a36Sopenharmony_ci	host->state = state_stop;
23662306a36Sopenharmony_ci	host->result = result;
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	u8 ack;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	DBG_LOW("kw_handle_interrupt(%s, isr: %x)\n",
24562306a36Sopenharmony_ci		__kw_state_names[host->state], isr);
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	if (host->state == state_idle) {
24862306a36Sopenharmony_ci		printk(KERN_WARNING "low_i2c: Keywest got an out of state"
24962306a36Sopenharmony_ci		       " interrupt, ignoring\n");
25062306a36Sopenharmony_ci		kw_write_reg(reg_isr, isr);
25162306a36Sopenharmony_ci		return;
25262306a36Sopenharmony_ci	}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	if (isr == 0) {
25562306a36Sopenharmony_ci		printk(KERN_WARNING "low_i2c: Timeout in i2c transfer"
25662306a36Sopenharmony_ci		       " on keywest !\n");
25762306a36Sopenharmony_ci		if (host->state != state_stop) {
25862306a36Sopenharmony_ci			kw_i2c_do_stop(host, -EIO);
25962306a36Sopenharmony_ci			return;
26062306a36Sopenharmony_ci		}
26162306a36Sopenharmony_ci		ack = kw_read_reg(reg_status);
26262306a36Sopenharmony_ci		if (ack & KW_I2C_STAT_BUSY)
26362306a36Sopenharmony_ci			kw_write_reg(reg_status, 0);
26462306a36Sopenharmony_ci		host->state = state_idle;
26562306a36Sopenharmony_ci		kw_write_reg(reg_ier, 0x00);
26662306a36Sopenharmony_ci		if (!host->polled)
26762306a36Sopenharmony_ci			complete(&host->complete);
26862306a36Sopenharmony_ci		return;
26962306a36Sopenharmony_ci	}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (isr & KW_I2C_IRQ_ADDR) {
27262306a36Sopenharmony_ci		ack = kw_read_reg(reg_status);
27362306a36Sopenharmony_ci		if (host->state != state_addr) {
27462306a36Sopenharmony_ci			WRONG_STATE("KW_I2C_IRQ_ADDR");
27562306a36Sopenharmony_ci			kw_i2c_do_stop(host, -EIO);
27662306a36Sopenharmony_ci		}
27762306a36Sopenharmony_ci		if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
27862306a36Sopenharmony_ci			host->result = -ENXIO;
27962306a36Sopenharmony_ci			host->state = state_stop;
28062306a36Sopenharmony_ci			DBG_LOW("KW: NAK on address\n");
28162306a36Sopenharmony_ci		} else {
28262306a36Sopenharmony_ci			if (host->len == 0)
28362306a36Sopenharmony_ci				kw_i2c_do_stop(host, 0);
28462306a36Sopenharmony_ci			else if (host->rw) {
28562306a36Sopenharmony_ci				host->state = state_read;
28662306a36Sopenharmony_ci				if (host->len > 1)
28762306a36Sopenharmony_ci					kw_write_reg(reg_control,
28862306a36Sopenharmony_ci						     KW_I2C_CTL_AAK);
28962306a36Sopenharmony_ci			} else {
29062306a36Sopenharmony_ci				host->state = state_write;
29162306a36Sopenharmony_ci				kw_write_reg(reg_data, *(host->data++));
29262306a36Sopenharmony_ci				host->len--;
29362306a36Sopenharmony_ci			}
29462306a36Sopenharmony_ci		}
29562306a36Sopenharmony_ci		kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
29662306a36Sopenharmony_ci	}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	if (isr & KW_I2C_IRQ_DATA) {
29962306a36Sopenharmony_ci		if (host->state == state_read) {
30062306a36Sopenharmony_ci			*(host->data++) = kw_read_reg(reg_data);
30162306a36Sopenharmony_ci			host->len--;
30262306a36Sopenharmony_ci			kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
30362306a36Sopenharmony_ci			if (host->len == 0)
30462306a36Sopenharmony_ci				host->state = state_stop;
30562306a36Sopenharmony_ci			else if (host->len == 1)
30662306a36Sopenharmony_ci				kw_write_reg(reg_control, 0);
30762306a36Sopenharmony_ci		} else if (host->state == state_write) {
30862306a36Sopenharmony_ci			ack = kw_read_reg(reg_status);
30962306a36Sopenharmony_ci			if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
31062306a36Sopenharmony_ci				DBG_LOW("KW: nack on data write\n");
31162306a36Sopenharmony_ci				host->result = -EFBIG;
31262306a36Sopenharmony_ci				host->state = state_stop;
31362306a36Sopenharmony_ci			} else if (host->len) {
31462306a36Sopenharmony_ci				kw_write_reg(reg_data, *(host->data++));
31562306a36Sopenharmony_ci				host->len--;
31662306a36Sopenharmony_ci			} else
31762306a36Sopenharmony_ci				kw_i2c_do_stop(host, 0);
31862306a36Sopenharmony_ci		} else {
31962306a36Sopenharmony_ci			WRONG_STATE("KW_I2C_IRQ_DATA");
32062306a36Sopenharmony_ci			if (host->state != state_stop)
32162306a36Sopenharmony_ci				kw_i2c_do_stop(host, -EIO);
32262306a36Sopenharmony_ci		}
32362306a36Sopenharmony_ci		kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	if (isr & KW_I2C_IRQ_STOP) {
32762306a36Sopenharmony_ci		kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);
32862306a36Sopenharmony_ci		if (host->state != state_stop) {
32962306a36Sopenharmony_ci			WRONG_STATE("KW_I2C_IRQ_STOP");
33062306a36Sopenharmony_ci			host->result = -EIO;
33162306a36Sopenharmony_ci		}
33262306a36Sopenharmony_ci		host->state = state_idle;
33362306a36Sopenharmony_ci		if (!host->polled)
33462306a36Sopenharmony_ci			complete(&host->complete);
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	/* Below should only happen in manual mode which we don't use ... */
33862306a36Sopenharmony_ci	if (isr & KW_I2C_IRQ_START)
33962306a36Sopenharmony_ci		kw_write_reg(reg_isr, KW_I2C_IRQ_START);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci/* Interrupt handler */
34462306a36Sopenharmony_cistatic irqreturn_t kw_i2c_irq(int irq, void *dev_id)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	struct pmac_i2c_host_kw *host = dev_id;
34762306a36Sopenharmony_ci	unsigned long flags;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	spin_lock_irqsave(&host->lock, flags);
35062306a36Sopenharmony_ci	del_timer(&host->timeout_timer);
35162306a36Sopenharmony_ci	kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr));
35262306a36Sopenharmony_ci	if (host->state != state_idle) {
35362306a36Sopenharmony_ci		host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
35462306a36Sopenharmony_ci		add_timer(&host->timeout_timer);
35562306a36Sopenharmony_ci	}
35662306a36Sopenharmony_ci	spin_unlock_irqrestore(&host->lock, flags);
35762306a36Sopenharmony_ci	return IRQ_HANDLED;
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_cistatic void kw_i2c_timeout(struct timer_list *t)
36162306a36Sopenharmony_ci{
36262306a36Sopenharmony_ci	struct pmac_i2c_host_kw *host = from_timer(host, t, timeout_timer);
36362306a36Sopenharmony_ci	unsigned long flags;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	spin_lock_irqsave(&host->lock, flags);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	/*
36862306a36Sopenharmony_ci	 * If the timer is pending, that means we raced with the
36962306a36Sopenharmony_ci	 * irq, in which case we just return
37062306a36Sopenharmony_ci	 */
37162306a36Sopenharmony_ci	if (timer_pending(&host->timeout_timer))
37262306a36Sopenharmony_ci		goto skip;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr));
37562306a36Sopenharmony_ci	if (host->state != state_idle) {
37662306a36Sopenharmony_ci		host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
37762306a36Sopenharmony_ci		add_timer(&host->timeout_timer);
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci skip:
38062306a36Sopenharmony_ci	spin_unlock_irqrestore(&host->lock, flags);
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_cistatic int kw_i2c_open(struct pmac_i2c_bus *bus)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	struct pmac_i2c_host_kw *host = bus->hostdata;
38662306a36Sopenharmony_ci	mutex_lock(&host->mutex);
38762306a36Sopenharmony_ci	return 0;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistatic void kw_i2c_close(struct pmac_i2c_bus *bus)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	struct pmac_i2c_host_kw *host = bus->hostdata;
39362306a36Sopenharmony_ci	mutex_unlock(&host->mutex);
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_cistatic int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
39762306a36Sopenharmony_ci		       u32 subaddr, u8 *data, int len)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	struct pmac_i2c_host_kw *host = bus->hostdata;
40062306a36Sopenharmony_ci	u8 mode_reg = host->speed;
40162306a36Sopenharmony_ci	int use_irq = host->irq && !bus->polled;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	/* Setup mode & subaddress if any */
40462306a36Sopenharmony_ci	switch(bus->mode) {
40562306a36Sopenharmony_ci	case pmac_i2c_mode_dumb:
40662306a36Sopenharmony_ci		return -EINVAL;
40762306a36Sopenharmony_ci	case pmac_i2c_mode_std:
40862306a36Sopenharmony_ci		mode_reg |= KW_I2C_MODE_STANDARD;
40962306a36Sopenharmony_ci		if (subsize != 0)
41062306a36Sopenharmony_ci			return -EINVAL;
41162306a36Sopenharmony_ci		break;
41262306a36Sopenharmony_ci	case pmac_i2c_mode_stdsub:
41362306a36Sopenharmony_ci		mode_reg |= KW_I2C_MODE_STANDARDSUB;
41462306a36Sopenharmony_ci		if (subsize != 1)
41562306a36Sopenharmony_ci			return -EINVAL;
41662306a36Sopenharmony_ci		break;
41762306a36Sopenharmony_ci	case pmac_i2c_mode_combined:
41862306a36Sopenharmony_ci		mode_reg |= KW_I2C_MODE_COMBINED;
41962306a36Sopenharmony_ci		if (subsize != 1)
42062306a36Sopenharmony_ci			return -EINVAL;
42162306a36Sopenharmony_ci		break;
42262306a36Sopenharmony_ci	}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	/* Setup channel & clear pending irqs */
42562306a36Sopenharmony_ci	kw_write_reg(reg_isr, kw_read_reg(reg_isr));
42662306a36Sopenharmony_ci	kw_write_reg(reg_mode, mode_reg | (bus->channel << 4));
42762306a36Sopenharmony_ci	kw_write_reg(reg_status, 0);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/* Set up address and r/w bit, strip possible stale bus number from
43062306a36Sopenharmony_ci	 * address top bits
43162306a36Sopenharmony_ci	 */
43262306a36Sopenharmony_ci	kw_write_reg(reg_addr, addrdir & 0xff);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	/* Set up the sub address */
43562306a36Sopenharmony_ci	if ((mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB
43662306a36Sopenharmony_ci	    || (mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED)
43762306a36Sopenharmony_ci		kw_write_reg(reg_subaddr, subaddr);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	/* Prepare for async operations */
44062306a36Sopenharmony_ci	host->data = data;
44162306a36Sopenharmony_ci	host->len = len;
44262306a36Sopenharmony_ci	host->state = state_addr;
44362306a36Sopenharmony_ci	host->result = 0;
44462306a36Sopenharmony_ci	host->rw = (addrdir & 1);
44562306a36Sopenharmony_ci	host->polled = bus->polled;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	/* Enable interrupt if not using polled mode and interrupt is
44862306a36Sopenharmony_ci	 * available
44962306a36Sopenharmony_ci	 */
45062306a36Sopenharmony_ci	if (use_irq) {
45162306a36Sopenharmony_ci		/* Clear completion */
45262306a36Sopenharmony_ci		reinit_completion(&host->complete);
45362306a36Sopenharmony_ci		/* Ack stale interrupts */
45462306a36Sopenharmony_ci		kw_write_reg(reg_isr, kw_read_reg(reg_isr));
45562306a36Sopenharmony_ci		/* Arm timeout */
45662306a36Sopenharmony_ci		host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
45762306a36Sopenharmony_ci		add_timer(&host->timeout_timer);
45862306a36Sopenharmony_ci		/* Enable emission */
45962306a36Sopenharmony_ci		kw_write_reg(reg_ier, KW_I2C_IRQ_MASK);
46062306a36Sopenharmony_ci	}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	/* Start sending address */
46362306a36Sopenharmony_ci	kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	/* Wait for completion */
46662306a36Sopenharmony_ci	if (use_irq)
46762306a36Sopenharmony_ci		wait_for_completion(&host->complete);
46862306a36Sopenharmony_ci	else {
46962306a36Sopenharmony_ci		while(host->state != state_idle) {
47062306a36Sopenharmony_ci			unsigned long flags;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci			u8 isr = kw_i2c_wait_interrupt(host);
47362306a36Sopenharmony_ci			spin_lock_irqsave(&host->lock, flags);
47462306a36Sopenharmony_ci			kw_i2c_handle_interrupt(host, isr);
47562306a36Sopenharmony_ci			spin_unlock_irqrestore(&host->lock, flags);
47662306a36Sopenharmony_ci		}
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	/* Disable emission */
48062306a36Sopenharmony_ci	kw_write_reg(reg_ier, 0);
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	return host->result;
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	struct pmac_i2c_host_kw *host;
48862306a36Sopenharmony_ci	const u32		*psteps, *prate, *addrp;
48962306a36Sopenharmony_ci	u32			steps;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	host = kzalloc(sizeof(*host), GFP_KERNEL);
49262306a36Sopenharmony_ci	if (host == NULL) {
49362306a36Sopenharmony_ci		printk(KERN_ERR "low_i2c: Can't allocate host for %pOF\n",
49462306a36Sopenharmony_ci		       np);
49562306a36Sopenharmony_ci		return NULL;
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	/* Apple is kind enough to provide a valid AAPL,address property
49962306a36Sopenharmony_ci	 * on all i2c keywest nodes so far ... we would have to fallback
50062306a36Sopenharmony_ci	 * to macio parsing if that wasn't the case
50162306a36Sopenharmony_ci	 */
50262306a36Sopenharmony_ci	addrp = of_get_property(np, "AAPL,address", NULL);
50362306a36Sopenharmony_ci	if (addrp == NULL) {
50462306a36Sopenharmony_ci		printk(KERN_ERR "low_i2c: Can't find address for %pOF\n",
50562306a36Sopenharmony_ci		       np);
50662306a36Sopenharmony_ci		kfree(host);
50762306a36Sopenharmony_ci		return NULL;
50862306a36Sopenharmony_ci	}
50962306a36Sopenharmony_ci	mutex_init(&host->mutex);
51062306a36Sopenharmony_ci	init_completion(&host->complete);
51162306a36Sopenharmony_ci	spin_lock_init(&host->lock);
51262306a36Sopenharmony_ci	timer_setup(&host->timeout_timer, kw_i2c_timeout, 0);
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	psteps = of_get_property(np, "AAPL,address-step", NULL);
51562306a36Sopenharmony_ci	steps = psteps ? (*psteps) : 0x10;
51662306a36Sopenharmony_ci	for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
51762306a36Sopenharmony_ci		steps >>= 1;
51862306a36Sopenharmony_ci	/* Select interface rate */
51962306a36Sopenharmony_ci	host->speed = KW_I2C_MODE_25KHZ;
52062306a36Sopenharmony_ci	prate = of_get_property(np, "AAPL,i2c-rate", NULL);
52162306a36Sopenharmony_ci	if (prate) switch(*prate) {
52262306a36Sopenharmony_ci	case 100:
52362306a36Sopenharmony_ci		host->speed = KW_I2C_MODE_100KHZ;
52462306a36Sopenharmony_ci		break;
52562306a36Sopenharmony_ci	case 50:
52662306a36Sopenharmony_ci		host->speed = KW_I2C_MODE_50KHZ;
52762306a36Sopenharmony_ci		break;
52862306a36Sopenharmony_ci	case 25:
52962306a36Sopenharmony_ci		host->speed = KW_I2C_MODE_25KHZ;
53062306a36Sopenharmony_ci		break;
53162306a36Sopenharmony_ci	}
53262306a36Sopenharmony_ci	host->irq = irq_of_parse_and_map(np, 0);
53362306a36Sopenharmony_ci	if (!host->irq)
53462306a36Sopenharmony_ci		printk(KERN_WARNING
53562306a36Sopenharmony_ci		       "low_i2c: Failed to map interrupt for %pOF\n",
53662306a36Sopenharmony_ci		       np);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	host->base = ioremap((*addrp), 0x1000);
53962306a36Sopenharmony_ci	if (host->base == NULL) {
54062306a36Sopenharmony_ci		printk(KERN_ERR "low_i2c: Can't map registers for %pOF\n",
54162306a36Sopenharmony_ci		       np);
54262306a36Sopenharmony_ci		kfree(host);
54362306a36Sopenharmony_ci		return NULL;
54462306a36Sopenharmony_ci	}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	/* Make sure IRQ is disabled */
54762306a36Sopenharmony_ci	kw_write_reg(reg_ier, 0);
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	/* Request chip interrupt. We set IRQF_NO_SUSPEND because we don't
55062306a36Sopenharmony_ci	 * want that interrupt disabled between the 2 passes of driver
55162306a36Sopenharmony_ci	 * suspend or we'll have issues running the pfuncs
55262306a36Sopenharmony_ci	 */
55362306a36Sopenharmony_ci	if (request_irq(host->irq, kw_i2c_irq, IRQF_NO_SUSPEND,
55462306a36Sopenharmony_ci			"keywest i2c", host))
55562306a36Sopenharmony_ci		host->irq = 0;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %pOF\n",
55862306a36Sopenharmony_ci	       *addrp, host->irq, np);
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	return host;
56162306a36Sopenharmony_ci}
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_cistatic void __init kw_i2c_add(struct pmac_i2c_host_kw *host,
56562306a36Sopenharmony_ci			      struct device_node *controller,
56662306a36Sopenharmony_ci			      struct device_node *busnode,
56762306a36Sopenharmony_ci			      int channel)
56862306a36Sopenharmony_ci{
56962306a36Sopenharmony_ci	struct pmac_i2c_bus *bus;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	bus = kzalloc(sizeof(struct pmac_i2c_bus), GFP_KERNEL);
57262306a36Sopenharmony_ci	if (bus == NULL)
57362306a36Sopenharmony_ci		return;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	bus->controller = of_node_get(controller);
57662306a36Sopenharmony_ci	bus->busnode = of_node_get(busnode);
57762306a36Sopenharmony_ci	bus->type = pmac_i2c_bus_keywest;
57862306a36Sopenharmony_ci	bus->hostdata = host;
57962306a36Sopenharmony_ci	bus->channel = channel;
58062306a36Sopenharmony_ci	bus->mode = pmac_i2c_mode_std;
58162306a36Sopenharmony_ci	bus->open = kw_i2c_open;
58262306a36Sopenharmony_ci	bus->close = kw_i2c_close;
58362306a36Sopenharmony_ci	bus->xfer = kw_i2c_xfer;
58462306a36Sopenharmony_ci	mutex_init(&bus->mutex);
58562306a36Sopenharmony_ci	lockdep_register_key(&bus->lock_key);
58662306a36Sopenharmony_ci	lockdep_set_class(&bus->mutex, &bus->lock_key);
58762306a36Sopenharmony_ci	if (controller == busnode)
58862306a36Sopenharmony_ci		bus->flags = pmac_i2c_multibus;
58962306a36Sopenharmony_ci	list_add(&bus->link, &pmac_i2c_busses);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	printk(KERN_INFO " channel %d bus %s\n", channel,
59262306a36Sopenharmony_ci	       (controller == busnode) ? "<multibus>" : busnode->full_name);
59362306a36Sopenharmony_ci}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_cistatic void __init kw_i2c_probe(void)
59662306a36Sopenharmony_ci{
59762306a36Sopenharmony_ci	struct device_node *np, *child, *parent;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	/* Probe keywest-i2c busses */
60062306a36Sopenharmony_ci	for_each_compatible_node(np, "i2c","keywest-i2c") {
60162306a36Sopenharmony_ci		struct pmac_i2c_host_kw *host;
60262306a36Sopenharmony_ci		int multibus;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci		/* Found one, init a host structure */
60562306a36Sopenharmony_ci		host = kw_i2c_host_init(np);
60662306a36Sopenharmony_ci		if (host == NULL)
60762306a36Sopenharmony_ci			continue;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci		/* Now check if we have a multibus setup (old style) or if we
61062306a36Sopenharmony_ci		 * have proper bus nodes. Note that the "new" way (proper bus
61162306a36Sopenharmony_ci		 * nodes) might cause us to not create some busses that are
61262306a36Sopenharmony_ci		 * kept hidden in the device-tree. In the future, we might
61362306a36Sopenharmony_ci		 * want to work around that by creating busses without a node
61462306a36Sopenharmony_ci		 * but not for now
61562306a36Sopenharmony_ci		 */
61662306a36Sopenharmony_ci		child = of_get_next_child(np, NULL);
61762306a36Sopenharmony_ci		multibus = !of_node_name_eq(child, "i2c-bus");
61862306a36Sopenharmony_ci		of_node_put(child);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci		/* For a multibus setup, we get the bus count based on the
62162306a36Sopenharmony_ci		 * parent type
62262306a36Sopenharmony_ci		 */
62362306a36Sopenharmony_ci		if (multibus) {
62462306a36Sopenharmony_ci			int chans, i;
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci			parent = of_get_parent(np);
62762306a36Sopenharmony_ci			if (parent == NULL)
62862306a36Sopenharmony_ci				continue;
62962306a36Sopenharmony_ci			chans = parent->name[0] == 'u' ? 2 : 1;
63062306a36Sopenharmony_ci			of_node_put(parent);
63162306a36Sopenharmony_ci			for (i = 0; i < chans; i++)
63262306a36Sopenharmony_ci				kw_i2c_add(host, np, np, i);
63362306a36Sopenharmony_ci		} else {
63462306a36Sopenharmony_ci			for_each_child_of_node(np, child) {
63562306a36Sopenharmony_ci				const u32 *reg = of_get_property(child,
63662306a36Sopenharmony_ci						"reg", NULL);
63762306a36Sopenharmony_ci				if (reg == NULL)
63862306a36Sopenharmony_ci					continue;
63962306a36Sopenharmony_ci				kw_i2c_add(host, np, child, *reg);
64062306a36Sopenharmony_ci			}
64162306a36Sopenharmony_ci		}
64262306a36Sopenharmony_ci	}
64362306a36Sopenharmony_ci}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci/*
64762306a36Sopenharmony_ci *
64862306a36Sopenharmony_ci * PMU implementation
64962306a36Sopenharmony_ci *
65062306a36Sopenharmony_ci */
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci#ifdef CONFIG_ADB_PMU
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci/*
65562306a36Sopenharmony_ci * i2c command block to the PMU
65662306a36Sopenharmony_ci */
65762306a36Sopenharmony_cistruct pmu_i2c_hdr {
65862306a36Sopenharmony_ci	u8	bus;
65962306a36Sopenharmony_ci	u8	mode;
66062306a36Sopenharmony_ci	u8	bus2;
66162306a36Sopenharmony_ci	u8	address;
66262306a36Sopenharmony_ci	u8	sub_addr;
66362306a36Sopenharmony_ci	u8	comb_addr;
66462306a36Sopenharmony_ci	u8	count;
66562306a36Sopenharmony_ci	u8	data[];
66662306a36Sopenharmony_ci};
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_cistatic void pmu_i2c_complete(struct adb_request *req)
66962306a36Sopenharmony_ci{
67062306a36Sopenharmony_ci	complete(req->arg);
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_cistatic int pmu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
67462306a36Sopenharmony_ci			u32 subaddr, u8 *data, int len)
67562306a36Sopenharmony_ci{
67662306a36Sopenharmony_ci	struct adb_request *req = bus->hostdata;
67762306a36Sopenharmony_ci	struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req->data[1];
67862306a36Sopenharmony_ci	struct completion comp;
67962306a36Sopenharmony_ci	int read = addrdir & 1;
68062306a36Sopenharmony_ci	int retry;
68162306a36Sopenharmony_ci	int rc = 0;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	/* For now, limit ourselves to 16 bytes transfers */
68462306a36Sopenharmony_ci	if (len > 16)
68562306a36Sopenharmony_ci		return -EINVAL;
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	init_completion(&comp);
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	for (retry = 0; retry < 16; retry++) {
69062306a36Sopenharmony_ci		memset(req, 0, sizeof(struct adb_request));
69162306a36Sopenharmony_ci		hdr->bus = bus->channel;
69262306a36Sopenharmony_ci		hdr->count = len;
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci		switch(bus->mode) {
69562306a36Sopenharmony_ci		case pmac_i2c_mode_std:
69662306a36Sopenharmony_ci			if (subsize != 0)
69762306a36Sopenharmony_ci				return -EINVAL;
69862306a36Sopenharmony_ci			hdr->address = addrdir;
69962306a36Sopenharmony_ci			hdr->mode = PMU_I2C_MODE_SIMPLE;
70062306a36Sopenharmony_ci			break;
70162306a36Sopenharmony_ci		case pmac_i2c_mode_stdsub:
70262306a36Sopenharmony_ci		case pmac_i2c_mode_combined:
70362306a36Sopenharmony_ci			if (subsize != 1)
70462306a36Sopenharmony_ci				return -EINVAL;
70562306a36Sopenharmony_ci			hdr->address = addrdir & 0xfe;
70662306a36Sopenharmony_ci			hdr->comb_addr = addrdir;
70762306a36Sopenharmony_ci			hdr->sub_addr = subaddr;
70862306a36Sopenharmony_ci			if (bus->mode == pmac_i2c_mode_stdsub)
70962306a36Sopenharmony_ci				hdr->mode = PMU_I2C_MODE_STDSUB;
71062306a36Sopenharmony_ci			else
71162306a36Sopenharmony_ci				hdr->mode = PMU_I2C_MODE_COMBINED;
71262306a36Sopenharmony_ci			break;
71362306a36Sopenharmony_ci		default:
71462306a36Sopenharmony_ci			return -EINVAL;
71562306a36Sopenharmony_ci		}
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci		reinit_completion(&comp);
71862306a36Sopenharmony_ci		req->data[0] = PMU_I2C_CMD;
71962306a36Sopenharmony_ci		req->reply[0] = 0xff;
72062306a36Sopenharmony_ci		req->nbytes = sizeof(struct pmu_i2c_hdr) + 1;
72162306a36Sopenharmony_ci		req->done = pmu_i2c_complete;
72262306a36Sopenharmony_ci		req->arg = &comp;
72362306a36Sopenharmony_ci		if (!read && len) {
72462306a36Sopenharmony_ci			memcpy(hdr->data, data, len);
72562306a36Sopenharmony_ci			req->nbytes += len;
72662306a36Sopenharmony_ci		}
72762306a36Sopenharmony_ci		rc = pmu_queue_request(req);
72862306a36Sopenharmony_ci		if (rc)
72962306a36Sopenharmony_ci			return rc;
73062306a36Sopenharmony_ci		wait_for_completion(&comp);
73162306a36Sopenharmony_ci		if (req->reply[0] == PMU_I2C_STATUS_OK)
73262306a36Sopenharmony_ci			break;
73362306a36Sopenharmony_ci		msleep(15);
73462306a36Sopenharmony_ci	}
73562306a36Sopenharmony_ci	if (req->reply[0] != PMU_I2C_STATUS_OK)
73662306a36Sopenharmony_ci		return -EIO;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	for (retry = 0; retry < 16; retry++) {
73962306a36Sopenharmony_ci		memset(req, 0, sizeof(struct adb_request));
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci		/* I know that looks like a lot, slow as hell, but darwin
74262306a36Sopenharmony_ci		 * does it so let's be on the safe side for now
74362306a36Sopenharmony_ci		 */
74462306a36Sopenharmony_ci		msleep(15);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci		hdr->bus = PMU_I2C_BUS_STATUS;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci		reinit_completion(&comp);
74962306a36Sopenharmony_ci		req->data[0] = PMU_I2C_CMD;
75062306a36Sopenharmony_ci		req->reply[0] = 0xff;
75162306a36Sopenharmony_ci		req->nbytes = 2;
75262306a36Sopenharmony_ci		req->done = pmu_i2c_complete;
75362306a36Sopenharmony_ci		req->arg = &comp;
75462306a36Sopenharmony_ci		rc = pmu_queue_request(req);
75562306a36Sopenharmony_ci		if (rc)
75662306a36Sopenharmony_ci			return rc;
75762306a36Sopenharmony_ci		wait_for_completion(&comp);
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci		if (req->reply[0] == PMU_I2C_STATUS_OK && !read)
76062306a36Sopenharmony_ci			return 0;
76162306a36Sopenharmony_ci		if (req->reply[0] == PMU_I2C_STATUS_DATAREAD && read) {
76262306a36Sopenharmony_ci			int rlen = req->reply_len - 1;
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci			if (rlen != len) {
76562306a36Sopenharmony_ci				printk(KERN_WARNING "low_i2c: PMU returned %d"
76662306a36Sopenharmony_ci				       " bytes, expected %d !\n", rlen, len);
76762306a36Sopenharmony_ci				return -EIO;
76862306a36Sopenharmony_ci			}
76962306a36Sopenharmony_ci			if (len)
77062306a36Sopenharmony_ci				memcpy(data, &req->reply[1], len);
77162306a36Sopenharmony_ci			return 0;
77262306a36Sopenharmony_ci		}
77362306a36Sopenharmony_ci	}
77462306a36Sopenharmony_ci	return -EIO;
77562306a36Sopenharmony_ci}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_cistatic void __init pmu_i2c_probe(void)
77862306a36Sopenharmony_ci{
77962306a36Sopenharmony_ci	struct pmac_i2c_bus *bus;
78062306a36Sopenharmony_ci	struct device_node *busnode;
78162306a36Sopenharmony_ci	int channel, sz;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	if (!pmu_present())
78462306a36Sopenharmony_ci		return;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	/* There might or might not be a "pmu-i2c" node, we use that
78762306a36Sopenharmony_ci	 * or via-pmu itself, whatever we find. I haven't seen a machine
78862306a36Sopenharmony_ci	 * with separate bus nodes, so we assume a multibus setup
78962306a36Sopenharmony_ci	 */
79062306a36Sopenharmony_ci	busnode = of_find_node_by_name(NULL, "pmu-i2c");
79162306a36Sopenharmony_ci	if (busnode == NULL)
79262306a36Sopenharmony_ci		busnode = of_find_node_by_name(NULL, "via-pmu");
79362306a36Sopenharmony_ci	if (busnode == NULL)
79462306a36Sopenharmony_ci		return;
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	printk(KERN_INFO "PMU i2c %pOF\n", busnode);
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	/*
79962306a36Sopenharmony_ci	 * We add bus 1 and 2 only for now, bus 0 is "special"
80062306a36Sopenharmony_ci	 */
80162306a36Sopenharmony_ci	for (channel = 1; channel <= 2; channel++) {
80262306a36Sopenharmony_ci		sz = sizeof(struct pmac_i2c_bus) + sizeof(struct adb_request);
80362306a36Sopenharmony_ci		bus = kzalloc(sz, GFP_KERNEL);
80462306a36Sopenharmony_ci		if (bus == NULL)
80562306a36Sopenharmony_ci			return;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci		bus->controller = busnode;
80862306a36Sopenharmony_ci		bus->busnode = busnode;
80962306a36Sopenharmony_ci		bus->type = pmac_i2c_bus_pmu;
81062306a36Sopenharmony_ci		bus->channel = channel;
81162306a36Sopenharmony_ci		bus->mode = pmac_i2c_mode_std;
81262306a36Sopenharmony_ci		bus->hostdata = bus + 1;
81362306a36Sopenharmony_ci		bus->xfer = pmu_i2c_xfer;
81462306a36Sopenharmony_ci		mutex_init(&bus->mutex);
81562306a36Sopenharmony_ci		lockdep_register_key(&bus->lock_key);
81662306a36Sopenharmony_ci		lockdep_set_class(&bus->mutex, &bus->lock_key);
81762306a36Sopenharmony_ci		bus->flags = pmac_i2c_multibus;
81862306a36Sopenharmony_ci		list_add(&bus->link, &pmac_i2c_busses);
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci		printk(KERN_INFO " channel %d bus <multibus>\n", channel);
82162306a36Sopenharmony_ci	}
82262306a36Sopenharmony_ci}
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci#endif /* CONFIG_ADB_PMU */
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci/*
82862306a36Sopenharmony_ci *
82962306a36Sopenharmony_ci * SMU implementation
83062306a36Sopenharmony_ci *
83162306a36Sopenharmony_ci */
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci#ifdef CONFIG_PMAC_SMU
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_cistatic void smu_i2c_complete(struct smu_i2c_cmd *cmd, void *misc)
83662306a36Sopenharmony_ci{
83762306a36Sopenharmony_ci	complete(misc);
83862306a36Sopenharmony_ci}
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_cistatic int smu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
84162306a36Sopenharmony_ci			u32 subaddr, u8 *data, int len)
84262306a36Sopenharmony_ci{
84362306a36Sopenharmony_ci	struct smu_i2c_cmd *cmd = bus->hostdata;
84462306a36Sopenharmony_ci	struct completion comp;
84562306a36Sopenharmony_ci	int read = addrdir & 1;
84662306a36Sopenharmony_ci	int rc = 0;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	if ((read && len > SMU_I2C_READ_MAX) ||
84962306a36Sopenharmony_ci	    ((!read) && len > SMU_I2C_WRITE_MAX))
85062306a36Sopenharmony_ci		return -EINVAL;
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	memset(cmd, 0, sizeof(struct smu_i2c_cmd));
85362306a36Sopenharmony_ci	cmd->info.bus = bus->channel;
85462306a36Sopenharmony_ci	cmd->info.devaddr = addrdir;
85562306a36Sopenharmony_ci	cmd->info.datalen = len;
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	switch(bus->mode) {
85862306a36Sopenharmony_ci	case pmac_i2c_mode_std:
85962306a36Sopenharmony_ci		if (subsize != 0)
86062306a36Sopenharmony_ci			return -EINVAL;
86162306a36Sopenharmony_ci		cmd->info.type = SMU_I2C_TRANSFER_SIMPLE;
86262306a36Sopenharmony_ci		break;
86362306a36Sopenharmony_ci	case pmac_i2c_mode_stdsub:
86462306a36Sopenharmony_ci	case pmac_i2c_mode_combined:
86562306a36Sopenharmony_ci		if (subsize > 3 || subsize < 1)
86662306a36Sopenharmony_ci			return -EINVAL;
86762306a36Sopenharmony_ci		cmd->info.sublen = subsize;
86862306a36Sopenharmony_ci		/* that's big-endian only but heh ! */
86962306a36Sopenharmony_ci		memcpy(&cmd->info.subaddr, ((char *)&subaddr) + (4 - subsize),
87062306a36Sopenharmony_ci		       subsize);
87162306a36Sopenharmony_ci		if (bus->mode == pmac_i2c_mode_stdsub)
87262306a36Sopenharmony_ci			cmd->info.type = SMU_I2C_TRANSFER_STDSUB;
87362306a36Sopenharmony_ci		else
87462306a36Sopenharmony_ci			cmd->info.type = SMU_I2C_TRANSFER_COMBINED;
87562306a36Sopenharmony_ci		break;
87662306a36Sopenharmony_ci	default:
87762306a36Sopenharmony_ci		return -EINVAL;
87862306a36Sopenharmony_ci	}
87962306a36Sopenharmony_ci	if (!read && len)
88062306a36Sopenharmony_ci		memcpy(cmd->info.data, data, len);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	init_completion(&comp);
88362306a36Sopenharmony_ci	cmd->done = smu_i2c_complete;
88462306a36Sopenharmony_ci	cmd->misc = &comp;
88562306a36Sopenharmony_ci	rc = smu_queue_i2c(cmd);
88662306a36Sopenharmony_ci	if (rc < 0)
88762306a36Sopenharmony_ci		return rc;
88862306a36Sopenharmony_ci	wait_for_completion(&comp);
88962306a36Sopenharmony_ci	rc = cmd->status;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	if (read && len)
89262306a36Sopenharmony_ci		memcpy(data, cmd->info.data, len);
89362306a36Sopenharmony_ci	return rc < 0 ? rc : 0;
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_cistatic void __init smu_i2c_probe(void)
89762306a36Sopenharmony_ci{
89862306a36Sopenharmony_ci	struct device_node *controller, *busnode;
89962306a36Sopenharmony_ci	struct pmac_i2c_bus *bus;
90062306a36Sopenharmony_ci	const u32 *reg;
90162306a36Sopenharmony_ci	int sz;
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	if (!smu_present())
90462306a36Sopenharmony_ci		return;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	controller = of_find_node_by_name(NULL, "smu-i2c-control");
90762306a36Sopenharmony_ci	if (controller == NULL)
90862306a36Sopenharmony_ci		controller = of_find_node_by_name(NULL, "smu");
90962306a36Sopenharmony_ci	if (controller == NULL)
91062306a36Sopenharmony_ci		return;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	printk(KERN_INFO "SMU i2c %pOF\n", controller);
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	/* Look for childs, note that they might not be of the right
91562306a36Sopenharmony_ci	 * type as older device trees mix i2c busses and other things
91662306a36Sopenharmony_ci	 * at the same level
91762306a36Sopenharmony_ci	 */
91862306a36Sopenharmony_ci	for_each_child_of_node(controller, busnode) {
91962306a36Sopenharmony_ci		if (!of_node_is_type(busnode, "i2c") &&
92062306a36Sopenharmony_ci		    !of_node_is_type(busnode, "i2c-bus"))
92162306a36Sopenharmony_ci			continue;
92262306a36Sopenharmony_ci		reg = of_get_property(busnode, "reg", NULL);
92362306a36Sopenharmony_ci		if (reg == NULL)
92462306a36Sopenharmony_ci			continue;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci		sz = sizeof(struct pmac_i2c_bus) + sizeof(struct smu_i2c_cmd);
92762306a36Sopenharmony_ci		bus = kzalloc(sz, GFP_KERNEL);
92862306a36Sopenharmony_ci		if (bus == NULL)
92962306a36Sopenharmony_ci			return;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci		bus->controller = controller;
93262306a36Sopenharmony_ci		bus->busnode = of_node_get(busnode);
93362306a36Sopenharmony_ci		bus->type = pmac_i2c_bus_smu;
93462306a36Sopenharmony_ci		bus->channel = *reg;
93562306a36Sopenharmony_ci		bus->mode = pmac_i2c_mode_std;
93662306a36Sopenharmony_ci		bus->hostdata = bus + 1;
93762306a36Sopenharmony_ci		bus->xfer = smu_i2c_xfer;
93862306a36Sopenharmony_ci		mutex_init(&bus->mutex);
93962306a36Sopenharmony_ci		lockdep_register_key(&bus->lock_key);
94062306a36Sopenharmony_ci		lockdep_set_class(&bus->mutex, &bus->lock_key);
94162306a36Sopenharmony_ci		bus->flags = 0;
94262306a36Sopenharmony_ci		list_add(&bus->link, &pmac_i2c_busses);
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci		printk(KERN_INFO " channel %x bus %pOF\n",
94562306a36Sopenharmony_ci		       bus->channel, busnode);
94662306a36Sopenharmony_ci	}
94762306a36Sopenharmony_ci}
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci#endif /* CONFIG_PMAC_SMU */
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci/*
95262306a36Sopenharmony_ci *
95362306a36Sopenharmony_ci * Core code
95462306a36Sopenharmony_ci *
95562306a36Sopenharmony_ci */
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_cistruct pmac_i2c_bus *pmac_i2c_find_bus(struct device_node *node)
95962306a36Sopenharmony_ci{
96062306a36Sopenharmony_ci	struct device_node *p = of_node_get(node);
96162306a36Sopenharmony_ci	struct device_node *prev = NULL;
96262306a36Sopenharmony_ci	struct pmac_i2c_bus *bus;
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	while(p) {
96562306a36Sopenharmony_ci		list_for_each_entry(bus, &pmac_i2c_busses, link) {
96662306a36Sopenharmony_ci			if (p == bus->busnode) {
96762306a36Sopenharmony_ci				if (prev && bus->flags & pmac_i2c_multibus) {
96862306a36Sopenharmony_ci					const u32 *reg;
96962306a36Sopenharmony_ci					reg = of_get_property(prev, "reg",
97062306a36Sopenharmony_ci								NULL);
97162306a36Sopenharmony_ci					if (!reg)
97262306a36Sopenharmony_ci						continue;
97362306a36Sopenharmony_ci					if (((*reg) >> 8) != bus->channel)
97462306a36Sopenharmony_ci						continue;
97562306a36Sopenharmony_ci				}
97662306a36Sopenharmony_ci				of_node_put(p);
97762306a36Sopenharmony_ci				of_node_put(prev);
97862306a36Sopenharmony_ci				return bus;
97962306a36Sopenharmony_ci			}
98062306a36Sopenharmony_ci		}
98162306a36Sopenharmony_ci		of_node_put(prev);
98262306a36Sopenharmony_ci		prev = p;
98362306a36Sopenharmony_ci		p = of_get_parent(p);
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci	return NULL;
98662306a36Sopenharmony_ci}
98762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_find_bus);
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ciu8 pmac_i2c_get_dev_addr(struct device_node *device)
99062306a36Sopenharmony_ci{
99162306a36Sopenharmony_ci	const u32 *reg = of_get_property(device, "reg", NULL);
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	if (reg == NULL)
99462306a36Sopenharmony_ci		return 0;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	return (*reg) & 0xff;
99762306a36Sopenharmony_ci}
99862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_get_dev_addr);
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_cistruct device_node *pmac_i2c_get_controller(struct pmac_i2c_bus *bus)
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	return bus->controller;
100362306a36Sopenharmony_ci}
100462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_get_controller);
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_cistruct device_node *pmac_i2c_get_bus_node(struct pmac_i2c_bus *bus)
100762306a36Sopenharmony_ci{
100862306a36Sopenharmony_ci	return bus->busnode;
100962306a36Sopenharmony_ci}
101062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_get_bus_node);
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ciint pmac_i2c_get_type(struct pmac_i2c_bus *bus)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	return bus->type;
101562306a36Sopenharmony_ci}
101662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_get_type);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ciint pmac_i2c_get_flags(struct pmac_i2c_bus *bus)
101962306a36Sopenharmony_ci{
102062306a36Sopenharmony_ci	return bus->flags;
102162306a36Sopenharmony_ci}
102262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_get_flags);
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ciint pmac_i2c_get_channel(struct pmac_i2c_bus *bus)
102562306a36Sopenharmony_ci{
102662306a36Sopenharmony_ci	return bus->channel;
102762306a36Sopenharmony_ci}
102862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_get_channel);
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_cistruct i2c_adapter *pmac_i2c_get_adapter(struct pmac_i2c_bus *bus)
103262306a36Sopenharmony_ci{
103362306a36Sopenharmony_ci	return &bus->adapter;
103462306a36Sopenharmony_ci}
103562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_get_adapter);
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_cistruct pmac_i2c_bus *pmac_i2c_adapter_to_bus(struct i2c_adapter *adapter)
103862306a36Sopenharmony_ci{
103962306a36Sopenharmony_ci	struct pmac_i2c_bus *bus;
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	list_for_each_entry(bus, &pmac_i2c_busses, link)
104262306a36Sopenharmony_ci		if (&bus->adapter == adapter)
104362306a36Sopenharmony_ci			return bus;
104462306a36Sopenharmony_ci	return NULL;
104562306a36Sopenharmony_ci}
104662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_adapter_to_bus);
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ciint pmac_i2c_match_adapter(struct device_node *dev, struct i2c_adapter *adapter)
104962306a36Sopenharmony_ci{
105062306a36Sopenharmony_ci	struct pmac_i2c_bus *bus = pmac_i2c_find_bus(dev);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	if (bus == NULL)
105362306a36Sopenharmony_ci		return 0;
105462306a36Sopenharmony_ci	return (&bus->adapter == adapter);
105562306a36Sopenharmony_ci}
105662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_match_adapter);
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ciint pmac_low_i2c_lock(struct device_node *np)
105962306a36Sopenharmony_ci{
106062306a36Sopenharmony_ci	struct pmac_i2c_bus *bus, *found = NULL;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	list_for_each_entry(bus, &pmac_i2c_busses, link) {
106362306a36Sopenharmony_ci		if (np == bus->controller) {
106462306a36Sopenharmony_ci			found = bus;
106562306a36Sopenharmony_ci			break;
106662306a36Sopenharmony_ci		}
106762306a36Sopenharmony_ci	}
106862306a36Sopenharmony_ci	if (!found)
106962306a36Sopenharmony_ci		return -ENODEV;
107062306a36Sopenharmony_ci	return pmac_i2c_open(bus, 0);
107162306a36Sopenharmony_ci}
107262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_low_i2c_lock);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ciint pmac_low_i2c_unlock(struct device_node *np)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	struct pmac_i2c_bus *bus, *found = NULL;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	list_for_each_entry(bus, &pmac_i2c_busses, link) {
107962306a36Sopenharmony_ci		if (np == bus->controller) {
108062306a36Sopenharmony_ci			found = bus;
108162306a36Sopenharmony_ci			break;
108262306a36Sopenharmony_ci		}
108362306a36Sopenharmony_ci	}
108462306a36Sopenharmony_ci	if (!found)
108562306a36Sopenharmony_ci		return -ENODEV;
108662306a36Sopenharmony_ci	pmac_i2c_close(bus);
108762306a36Sopenharmony_ci	return 0;
108862306a36Sopenharmony_ci}
108962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_low_i2c_unlock);
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ciint pmac_i2c_open(struct pmac_i2c_bus *bus, int polled)
109362306a36Sopenharmony_ci{
109462306a36Sopenharmony_ci	int rc;
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	mutex_lock(&bus->mutex);
109762306a36Sopenharmony_ci	bus->polled = polled || pmac_i2c_force_poll;
109862306a36Sopenharmony_ci	bus->opened = 1;
109962306a36Sopenharmony_ci	bus->mode = pmac_i2c_mode_std;
110062306a36Sopenharmony_ci	if (bus->open && (rc = bus->open(bus)) != 0) {
110162306a36Sopenharmony_ci		bus->opened = 0;
110262306a36Sopenharmony_ci		mutex_unlock(&bus->mutex);
110362306a36Sopenharmony_ci		return rc;
110462306a36Sopenharmony_ci	}
110562306a36Sopenharmony_ci	return 0;
110662306a36Sopenharmony_ci}
110762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_open);
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_civoid pmac_i2c_close(struct pmac_i2c_bus *bus)
111062306a36Sopenharmony_ci{
111162306a36Sopenharmony_ci	WARN_ON(!bus->opened);
111262306a36Sopenharmony_ci	if (bus->close)
111362306a36Sopenharmony_ci		bus->close(bus);
111462306a36Sopenharmony_ci	bus->opened = 0;
111562306a36Sopenharmony_ci	mutex_unlock(&bus->mutex);
111662306a36Sopenharmony_ci}
111762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_close);
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ciint pmac_i2c_setmode(struct pmac_i2c_bus *bus, int mode)
112062306a36Sopenharmony_ci{
112162306a36Sopenharmony_ci	WARN_ON(!bus->opened);
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	/* Report me if you see the error below as there might be a new
112462306a36Sopenharmony_ci	 * "combined4" mode that I need to implement for the SMU bus
112562306a36Sopenharmony_ci	 */
112662306a36Sopenharmony_ci	if (mode < pmac_i2c_mode_dumb || mode > pmac_i2c_mode_combined) {
112762306a36Sopenharmony_ci		printk(KERN_ERR "low_i2c: Invalid mode %d requested on"
112862306a36Sopenharmony_ci		       " bus %pOF !\n", mode, bus->busnode);
112962306a36Sopenharmony_ci		return -EINVAL;
113062306a36Sopenharmony_ci	}
113162306a36Sopenharmony_ci	bus->mode = mode;
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	return 0;
113462306a36Sopenharmony_ci}
113562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_setmode);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ciint pmac_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
113862306a36Sopenharmony_ci		  u32 subaddr, u8 *data, int len)
113962306a36Sopenharmony_ci{
114062306a36Sopenharmony_ci	int rc;
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	WARN_ON(!bus->opened);
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	DBG("xfer() chan=%d, addrdir=0x%x, mode=%d, subsize=%d, subaddr=0x%x,"
114562306a36Sopenharmony_ci	    " %d bytes, bus %pOF\n", bus->channel, addrdir, bus->mode, subsize,
114662306a36Sopenharmony_ci	    subaddr, len, bus->busnode);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	rc = bus->xfer(bus, addrdir, subsize, subaddr, data, len);
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci#ifdef DEBUG
115162306a36Sopenharmony_ci	if (rc)
115262306a36Sopenharmony_ci		DBG("xfer error %d\n", rc);
115362306a36Sopenharmony_ci#endif
115462306a36Sopenharmony_ci	return rc;
115562306a36Sopenharmony_ci}
115662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pmac_i2c_xfer);
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci/* some quirks for platform function decoding */
115962306a36Sopenharmony_cienum {
116062306a36Sopenharmony_ci	pmac_i2c_quirk_invmask = 0x00000001u,
116162306a36Sopenharmony_ci	pmac_i2c_quirk_skip = 0x00000002u,
116262306a36Sopenharmony_ci};
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_cistatic void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
116562306a36Sopenharmony_ci					      int quirks))
116662306a36Sopenharmony_ci{
116762306a36Sopenharmony_ci	struct pmac_i2c_bus *bus;
116862306a36Sopenharmony_ci	struct device_node *np;
116962306a36Sopenharmony_ci	static struct whitelist_ent {
117062306a36Sopenharmony_ci		char *name;
117162306a36Sopenharmony_ci		char *compatible;
117262306a36Sopenharmony_ci		int quirks;
117362306a36Sopenharmony_ci	} whitelist[] = {
117462306a36Sopenharmony_ci		/* XXX Study device-tree's & apple drivers are get the quirks
117562306a36Sopenharmony_ci		 * right !
117662306a36Sopenharmony_ci		 */
117762306a36Sopenharmony_ci		/* Workaround: It seems that running the clockspreading
117862306a36Sopenharmony_ci		 * properties on the eMac will cause lockups during boot.
117962306a36Sopenharmony_ci		 * The machine seems to work fine without that. So for now,
118062306a36Sopenharmony_ci		 * let's make sure i2c-hwclock doesn't match about "imic"
118162306a36Sopenharmony_ci		 * clocks and we'll figure out if we really need to do
118262306a36Sopenharmony_ci		 * something special about those later.
118362306a36Sopenharmony_ci		 */
118462306a36Sopenharmony_ci		{ "i2c-hwclock", "imic5002", pmac_i2c_quirk_skip },
118562306a36Sopenharmony_ci		{ "i2c-hwclock", "imic5003", pmac_i2c_quirk_skip },
118662306a36Sopenharmony_ci		{ "i2c-hwclock", NULL, pmac_i2c_quirk_invmask },
118762306a36Sopenharmony_ci		{ "i2c-cpu-voltage", NULL, 0},
118862306a36Sopenharmony_ci		{  "temp-monitor", NULL, 0 },
118962306a36Sopenharmony_ci		{  "supply-monitor", NULL, 0 },
119062306a36Sopenharmony_ci		{ NULL, NULL, 0 },
119162306a36Sopenharmony_ci	};
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	/* Only some devices need to have platform functions instantiated
119462306a36Sopenharmony_ci	 * here. For now, we have a table. Others, like 9554 i2c GPIOs used
119562306a36Sopenharmony_ci	 * on Xserve, if we ever do a driver for them, will use their own
119662306a36Sopenharmony_ci	 * platform function instance
119762306a36Sopenharmony_ci	 */
119862306a36Sopenharmony_ci	list_for_each_entry(bus, &pmac_i2c_busses, link) {
119962306a36Sopenharmony_ci		for_each_child_of_node(bus->busnode, np) {
120062306a36Sopenharmony_ci			struct whitelist_ent *p;
120162306a36Sopenharmony_ci			/* If multibus, check if device is on that bus */
120262306a36Sopenharmony_ci			if (bus->flags & pmac_i2c_multibus)
120362306a36Sopenharmony_ci				if (bus != pmac_i2c_find_bus(np))
120462306a36Sopenharmony_ci					continue;
120562306a36Sopenharmony_ci			for (p = whitelist; p->name != NULL; p++) {
120662306a36Sopenharmony_ci				if (!of_node_name_eq(np, p->name))
120762306a36Sopenharmony_ci					continue;
120862306a36Sopenharmony_ci				if (p->compatible &&
120962306a36Sopenharmony_ci				    !of_device_is_compatible(np, p->compatible))
121062306a36Sopenharmony_ci					continue;
121162306a36Sopenharmony_ci				if (p->quirks & pmac_i2c_quirk_skip)
121262306a36Sopenharmony_ci					break;
121362306a36Sopenharmony_ci				callback(np, p->quirks);
121462306a36Sopenharmony_ci				break;
121562306a36Sopenharmony_ci			}
121662306a36Sopenharmony_ci		}
121762306a36Sopenharmony_ci	}
121862306a36Sopenharmony_ci}
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci#define MAX_I2C_DATA	64
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_cistruct pmac_i2c_pf_inst
122362306a36Sopenharmony_ci{
122462306a36Sopenharmony_ci	struct pmac_i2c_bus	*bus;
122562306a36Sopenharmony_ci	u8			addr;
122662306a36Sopenharmony_ci	u8			buffer[MAX_I2C_DATA];
122762306a36Sopenharmony_ci	u8			scratch[MAX_I2C_DATA];
122862306a36Sopenharmony_ci	int			bytes;
122962306a36Sopenharmony_ci	int			quirks;
123062306a36Sopenharmony_ci};
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_cistatic void* pmac_i2c_do_begin(struct pmf_function *func, struct pmf_args *args)
123362306a36Sopenharmony_ci{
123462306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst;
123562306a36Sopenharmony_ci	struct pmac_i2c_bus	*bus;
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	bus = pmac_i2c_find_bus(func->node);
123862306a36Sopenharmony_ci	if (bus == NULL) {
123962306a36Sopenharmony_ci		printk(KERN_ERR "low_i2c: Can't find bus for %pOF (pfunc)\n",
124062306a36Sopenharmony_ci		       func->node);
124162306a36Sopenharmony_ci		return NULL;
124262306a36Sopenharmony_ci	}
124362306a36Sopenharmony_ci	if (pmac_i2c_open(bus, 0)) {
124462306a36Sopenharmony_ci		printk(KERN_ERR "low_i2c: Can't open i2c bus for %pOF (pfunc)\n",
124562306a36Sopenharmony_ci		       func->node);
124662306a36Sopenharmony_ci		return NULL;
124762306a36Sopenharmony_ci	}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	/* XXX might need GFP_ATOMIC when called during the suspend process,
125062306a36Sopenharmony_ci	 * but then, there are already lots of issues with suspending when
125162306a36Sopenharmony_ci	 * near OOM that need to be resolved, the allocator itself should
125262306a36Sopenharmony_ci	 * probably make GFP_NOIO implicit during suspend
125362306a36Sopenharmony_ci	 */
125462306a36Sopenharmony_ci	inst = kzalloc(sizeof(struct pmac_i2c_pf_inst), GFP_KERNEL);
125562306a36Sopenharmony_ci	if (inst == NULL) {
125662306a36Sopenharmony_ci		pmac_i2c_close(bus);
125762306a36Sopenharmony_ci		return NULL;
125862306a36Sopenharmony_ci	}
125962306a36Sopenharmony_ci	inst->bus = bus;
126062306a36Sopenharmony_ci	inst->addr = pmac_i2c_get_dev_addr(func->node);
126162306a36Sopenharmony_ci	inst->quirks = (int)(long)func->driver_data;
126262306a36Sopenharmony_ci	return inst;
126362306a36Sopenharmony_ci}
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_cistatic void pmac_i2c_do_end(struct pmf_function *func, void *instdata)
126662306a36Sopenharmony_ci{
126762306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	if (inst == NULL)
127062306a36Sopenharmony_ci		return;
127162306a36Sopenharmony_ci	pmac_i2c_close(inst->bus);
127262306a36Sopenharmony_ci	kfree(inst);
127362306a36Sopenharmony_ci}
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_cistatic int pmac_i2c_do_read(PMF_STD_ARGS, u32 len)
127662306a36Sopenharmony_ci{
127762306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	inst->bytes = len;
128062306a36Sopenharmony_ci	return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_read, 0, 0,
128162306a36Sopenharmony_ci			     inst->buffer, len);
128262306a36Sopenharmony_ci}
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_cistatic int pmac_i2c_do_write(PMF_STD_ARGS, u32 len, const u8 *data)
128562306a36Sopenharmony_ci{
128662306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_write, 0, 0,
128962306a36Sopenharmony_ci			     (u8 *)data, len);
129062306a36Sopenharmony_ci}
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci/* This function is used to do the masking & OR'ing for the "rmw" type
129362306a36Sopenharmony_ci * callbacks. Ze should apply the mask and OR in the values in the
129462306a36Sopenharmony_ci * buffer before writing back. The problem is that it seems that
129562306a36Sopenharmony_ci * various darwin drivers implement the mask/or differently, thus
129662306a36Sopenharmony_ci * we need to check the quirks first
129762306a36Sopenharmony_ci */
129862306a36Sopenharmony_cistatic void pmac_i2c_do_apply_rmw(struct pmac_i2c_pf_inst *inst,
129962306a36Sopenharmony_ci				  u32 len, const u8 *mask, const u8 *val)
130062306a36Sopenharmony_ci{
130162306a36Sopenharmony_ci	int i;
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	if (inst->quirks & pmac_i2c_quirk_invmask) {
130462306a36Sopenharmony_ci		for (i = 0; i < len; i ++)
130562306a36Sopenharmony_ci			inst->scratch[i] = (inst->buffer[i] & mask[i]) | val[i];
130662306a36Sopenharmony_ci	} else {
130762306a36Sopenharmony_ci		for (i = 0; i < len; i ++)
130862306a36Sopenharmony_ci			inst->scratch[i] = (inst->buffer[i] & ~mask[i])
130962306a36Sopenharmony_ci				| (val[i] & mask[i]);
131062306a36Sopenharmony_ci	}
131162306a36Sopenharmony_ci}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_cistatic int pmac_i2c_do_rmw(PMF_STD_ARGS, u32 masklen, u32 valuelen,
131462306a36Sopenharmony_ci			   u32 totallen, const u8 *maskdata,
131562306a36Sopenharmony_ci			   const u8 *valuedata)
131662306a36Sopenharmony_ci{
131762306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	if (masklen > inst->bytes || valuelen > inst->bytes ||
132062306a36Sopenharmony_ci	    totallen > inst->bytes || valuelen > masklen)
132162306a36Sopenharmony_ci		return -EINVAL;
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	pmac_i2c_do_apply_rmw(inst, masklen, maskdata, valuedata);
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_write, 0, 0,
132662306a36Sopenharmony_ci			     inst->scratch, totallen);
132762306a36Sopenharmony_ci}
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_cistatic int pmac_i2c_do_read_sub(PMF_STD_ARGS, u8 subaddr, u32 len)
133062306a36Sopenharmony_ci{
133162306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	inst->bytes = len;
133462306a36Sopenharmony_ci	return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_read, 1, subaddr,
133562306a36Sopenharmony_ci			     inst->buffer, len);
133662306a36Sopenharmony_ci}
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_cistatic int pmac_i2c_do_write_sub(PMF_STD_ARGS, u8 subaddr, u32 len,
133962306a36Sopenharmony_ci				     const u8 *data)
134062306a36Sopenharmony_ci{
134162306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_write, 1,
134462306a36Sopenharmony_ci			     subaddr, (u8 *)data, len);
134562306a36Sopenharmony_ci}
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_cistatic int pmac_i2c_do_set_mode(PMF_STD_ARGS, int mode)
134862306a36Sopenharmony_ci{
134962306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	return pmac_i2c_setmode(inst->bus, mode);
135262306a36Sopenharmony_ci}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_cistatic int pmac_i2c_do_rmw_sub(PMF_STD_ARGS, u8 subaddr, u32 masklen,
135562306a36Sopenharmony_ci			       u32 valuelen, u32 totallen, const u8 *maskdata,
135662306a36Sopenharmony_ci			       const u8 *valuedata)
135762306a36Sopenharmony_ci{
135862306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	if (masklen > inst->bytes || valuelen > inst->bytes ||
136162306a36Sopenharmony_ci	    totallen > inst->bytes || valuelen > masklen)
136262306a36Sopenharmony_ci		return -EINVAL;
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	pmac_i2c_do_apply_rmw(inst, masklen, maskdata, valuedata);
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_write, 1,
136762306a36Sopenharmony_ci			     subaddr, inst->scratch, totallen);
136862306a36Sopenharmony_ci}
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_cistatic int pmac_i2c_do_mask_and_comp(PMF_STD_ARGS, u32 len,
137162306a36Sopenharmony_ci				     const u8 *maskdata,
137262306a36Sopenharmony_ci				     const u8 *valuedata)
137362306a36Sopenharmony_ci{
137462306a36Sopenharmony_ci	struct pmac_i2c_pf_inst *inst = instdata;
137562306a36Sopenharmony_ci	int i, match;
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	/* Get return value pointer, it's assumed to be a u32 */
137862306a36Sopenharmony_ci	if (!args || !args->count || !args->u[0].p)
137962306a36Sopenharmony_ci		return -EINVAL;
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	/* Check buffer */
138262306a36Sopenharmony_ci	if (len > inst->bytes)
138362306a36Sopenharmony_ci		return -EINVAL;
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	for (i = 0, match = 1; match && i < len; i ++)
138662306a36Sopenharmony_ci		if ((inst->buffer[i] & maskdata[i]) != valuedata[i])
138762306a36Sopenharmony_ci			match = 0;
138862306a36Sopenharmony_ci	*args->u[0].p = match;
138962306a36Sopenharmony_ci	return 0;
139062306a36Sopenharmony_ci}
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_cistatic int pmac_i2c_do_delay(PMF_STD_ARGS, u32 duration)
139362306a36Sopenharmony_ci{
139462306a36Sopenharmony_ci	msleep((duration + 999) / 1000);
139562306a36Sopenharmony_ci	return 0;
139662306a36Sopenharmony_ci}
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_cistatic struct pmf_handlers pmac_i2c_pfunc_handlers = {
140062306a36Sopenharmony_ci	.begin			= pmac_i2c_do_begin,
140162306a36Sopenharmony_ci	.end			= pmac_i2c_do_end,
140262306a36Sopenharmony_ci	.read_i2c		= pmac_i2c_do_read,
140362306a36Sopenharmony_ci	.write_i2c		= pmac_i2c_do_write,
140462306a36Sopenharmony_ci	.rmw_i2c		= pmac_i2c_do_rmw,
140562306a36Sopenharmony_ci	.read_i2c_sub		= pmac_i2c_do_read_sub,
140662306a36Sopenharmony_ci	.write_i2c_sub		= pmac_i2c_do_write_sub,
140762306a36Sopenharmony_ci	.rmw_i2c_sub		= pmac_i2c_do_rmw_sub,
140862306a36Sopenharmony_ci	.set_i2c_mode		= pmac_i2c_do_set_mode,
140962306a36Sopenharmony_ci	.mask_and_compare	= pmac_i2c_do_mask_and_comp,
141062306a36Sopenharmony_ci	.delay			= pmac_i2c_do_delay,
141162306a36Sopenharmony_ci};
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_cistatic void __init pmac_i2c_dev_create(struct device_node *np, int quirks)
141462306a36Sopenharmony_ci{
141562306a36Sopenharmony_ci	DBG("dev_create(%pOF)\n", np);
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	pmf_register_driver(np, &pmac_i2c_pfunc_handlers,
141862306a36Sopenharmony_ci			    (void *)(long)quirks);
141962306a36Sopenharmony_ci}
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_cistatic void __init pmac_i2c_dev_init(struct device_node *np, int quirks)
142262306a36Sopenharmony_ci{
142362306a36Sopenharmony_ci	DBG("dev_create(%pOF)\n", np);
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci	pmf_do_functions(np, NULL, 0, PMF_FLAGS_ON_INIT, NULL);
142662306a36Sopenharmony_ci}
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_cistatic void pmac_i2c_dev_suspend(struct device_node *np, int quirks)
142962306a36Sopenharmony_ci{
143062306a36Sopenharmony_ci	DBG("dev_suspend(%pOF)\n", np);
143162306a36Sopenharmony_ci	pmf_do_functions(np, NULL, 0, PMF_FLAGS_ON_SLEEP, NULL);
143262306a36Sopenharmony_ci}
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_cistatic void pmac_i2c_dev_resume(struct device_node *np, int quirks)
143562306a36Sopenharmony_ci{
143662306a36Sopenharmony_ci	DBG("dev_resume(%pOF)\n", np);
143762306a36Sopenharmony_ci	pmf_do_functions(np, NULL, 0, PMF_FLAGS_ON_WAKE, NULL);
143862306a36Sopenharmony_ci}
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_civoid pmac_pfunc_i2c_suspend(void)
144162306a36Sopenharmony_ci{
144262306a36Sopenharmony_ci	pmac_i2c_devscan(pmac_i2c_dev_suspend);
144362306a36Sopenharmony_ci}
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_civoid pmac_pfunc_i2c_resume(void)
144662306a36Sopenharmony_ci{
144762306a36Sopenharmony_ci	pmac_i2c_devscan(pmac_i2c_dev_resume);
144862306a36Sopenharmony_ci}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci/*
145162306a36Sopenharmony_ci * Initialize us: probe all i2c busses on the machine, instantiate
145262306a36Sopenharmony_ci * busses and platform functions as needed.
145362306a36Sopenharmony_ci */
145462306a36Sopenharmony_ci/* This is non-static as it might be called early by smp code */
145562306a36Sopenharmony_ciint __init pmac_i2c_init(void)
145662306a36Sopenharmony_ci{
145762306a36Sopenharmony_ci	static int i2c_inited;
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci	if (i2c_inited)
146062306a36Sopenharmony_ci		return 0;
146162306a36Sopenharmony_ci	i2c_inited = 1;
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	/* Probe keywest-i2c busses */
146462306a36Sopenharmony_ci	kw_i2c_probe();
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci#ifdef CONFIG_ADB_PMU
146762306a36Sopenharmony_ci	/* Probe PMU i2c busses */
146862306a36Sopenharmony_ci	pmu_i2c_probe();
146962306a36Sopenharmony_ci#endif
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci#ifdef CONFIG_PMAC_SMU
147262306a36Sopenharmony_ci	/* Probe SMU i2c busses */
147362306a36Sopenharmony_ci	smu_i2c_probe();
147462306a36Sopenharmony_ci#endif
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	/* Now add platform functions for some known devices */
147762306a36Sopenharmony_ci	pmac_i2c_devscan(pmac_i2c_dev_create);
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	return 0;
148062306a36Sopenharmony_ci}
148162306a36Sopenharmony_cimachine_arch_initcall(powermac, pmac_i2c_init);
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci/* Since pmac_i2c_init can be called too early for the platform device
148462306a36Sopenharmony_ci * registration, we need to do it at a later time. In our case, subsys
148562306a36Sopenharmony_ci * happens to fit well, though I agree it's a bit of a hack...
148662306a36Sopenharmony_ci */
148762306a36Sopenharmony_cistatic int __init pmac_i2c_create_platform_devices(void)
148862306a36Sopenharmony_ci{
148962306a36Sopenharmony_ci	struct pmac_i2c_bus *bus;
149062306a36Sopenharmony_ci	int i = 0;
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	/* In the case where we are initialized from smp_init(), we must
149362306a36Sopenharmony_ci	 * not use the timer (and thus the irq). It's safe from now on
149462306a36Sopenharmony_ci	 * though
149562306a36Sopenharmony_ci	 */
149662306a36Sopenharmony_ci	pmac_i2c_force_poll = 0;
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	/* Create platform devices */
149962306a36Sopenharmony_ci	list_for_each_entry(bus, &pmac_i2c_busses, link) {
150062306a36Sopenharmony_ci		bus->platform_dev =
150162306a36Sopenharmony_ci			platform_device_alloc("i2c-powermac", i++);
150262306a36Sopenharmony_ci		if (bus->platform_dev == NULL)
150362306a36Sopenharmony_ci			return -ENOMEM;
150462306a36Sopenharmony_ci		bus->platform_dev->dev.platform_data = bus;
150562306a36Sopenharmony_ci		bus->platform_dev->dev.of_node = bus->busnode;
150662306a36Sopenharmony_ci		platform_device_add(bus->platform_dev);
150762306a36Sopenharmony_ci	}
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	/* Now call platform "init" functions */
151062306a36Sopenharmony_ci	pmac_i2c_devscan(pmac_i2c_dev_init);
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	return 0;
151362306a36Sopenharmony_ci}
151462306a36Sopenharmony_cimachine_subsys_initcall(powermac, pmac_i2c_create_platform_devices);
1515