locomo.c revision fced80c735941fa518ac67c0b61bbe153fb8c050
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/arch/arm/common/locomo.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sharp LoCoMo support
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file contains all generic LoCoMo support.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All initialization functions provided here are intended to be called
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from machine specific code with proper arguments when required.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on sa1111.c
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
24d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
27fced80c735941fa518ac67c0b61bbe153fb8c050Russell King#include <linux/io.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/hardware.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mach/irq.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hardware/locomo.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* M62332 output channel selection */
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_EVR_CH	1	/* M62332 volume channel number  */
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*   0 : CH.1 , 1 : CH. 2        */
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DAC send data */
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	M62332_SLAVE_ADDR	0x4e	/* Slave address  */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	M62332_W_BIT		0x00	/* W bit (0 only) */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	M62332_SUB_ADDR		0x00	/* Sub address    */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	M62332_A_BIT		0x00	/* A bit (0 only) */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DAC setup and hold times (expressed in us) */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_BUS_FREE_TIME	5	/*   4.7 us */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_START_SETUP_TIME	5	/*   4.7 us */
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_STOP_SETUP_TIME	4	/*   4.0 us */
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_START_HOLD_TIME	5	/*   4.7 us */
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_SCL_LOW_HOLD_TIME	5	/*   4.7 us */
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_SCL_HIGH_HOLD_TIME	4	/*   4.0 us */
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_DATA_SETUP_TIME	1	/*   250 ns */
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_DATA_HOLD_TIME	1	/*   300 ns */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_LOW_SETUP_TIME	1	/*   300 ns */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_HIGH_SETUP_TIME	1	/*  1000 ns */
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the following is the overall data for the locomo chip */
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct locomo {
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device *dev;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long phys;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int irq;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t lock;
62548153663bbf33ca7c244a6bbddd82c26a17c331Russell King	void __iomem *base;
6393160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki#ifdef CONFIG_PM
6493160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki	void *saved_state;
6593160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki#endif
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct locomo_dev_info {
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	offset;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	length;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	devid;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	irq[1];
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *	name;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* All the locomo devices.  If offset is non-zero, the mapbase for the
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locomo_dev will be set to the chip base plus offset.  If offset is
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zero, then the mapbase for the locomo_dev will be set to zero.  An
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * offset of zero means the device only uses GPIOs or other helper
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * functions inside this file */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct locomo_dev_info locomo_devices[] = {
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid 		= LOCOMO_DEVID_KEYBOARD,
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq = {
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			IRQ_LOCOMO_KEY,
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-keyboard",
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_KEYBOARD,
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 16,
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_FRONTLIGHT,
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq		= {},
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-frontlight",
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_FRONTLIGHT,
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 8,
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_BACKLIGHT,
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq		= {},
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-backlight",
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_BACKLIGHT,
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 8,
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_AUDIO,
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq		= {},
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-audio",
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_AUDIO,
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 4,
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_LED,
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq 		= {},
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-led",
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_LED,
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 8,
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_UART,
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq		= {},
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-uart",
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= 0,
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 0,
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
127a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	{
128a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer		.devid		= LOCOMO_DEVID_SPI,
129a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer		.irq		= {},
130a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer		.name		= "locomo-spi",
131a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer		.offset		= LOCOMO_SPI,
132a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer		.length		= 0x30,
133a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	},
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** LoCoMo interrupt handling stuff.
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: LoCoMo has a 1 to many mapping on all of its IRQs.
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that is, there is only one real hardware interrupt
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we determine which interrupt it is by reading some IO memory.
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We have two levels of expansion, first in the handler for the
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hardware interrupt we generate an interrupt
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_*_BASE and those handlers generate more interrupts
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hardware irq reads LOCOMO_ICR & 0x0f00
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_KEY_BASE
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_GPIO_BASE
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_LT_BASE
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_BASE
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_KEY_BASE reads LOCOMO_KIC & 0x0001
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_KEY
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_GPIO_BASE reads LOCOMO_GIR & LOCOMO_GPD & 0xffff
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_GPIO[0-15]
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_LT_BASE reads LOCOMO_LTINT & 0x0001
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_LT
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_SPI_BASE reads LOCOMO_SPIIR & 0x000F
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_RFR
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_RFW
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_OVRN
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_TEND
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_START	(IRQ_LOCOMO_KEY_BASE)
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_KEY_START	(IRQ_LOCOMO_KEY)
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LOCOMO_IRQ_GPIO_START	(IRQ_LOCOMO_GPIO0)
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LOCOMO_IRQ_LT_START	(IRQ_LOCOMO_LT)
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LOCOMO_IRQ_SPI_START	(IRQ_LOCOMO_SPI_RFR)
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16910dd5ce28d78e2440e8fa1135d17e33399d75340Russell Kingstatic void locomo_handler(unsigned int irq, struct irq_desc *desc)
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int req, i;
17210dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	struct irq_desc *d;
17310dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Acknowledge the parent IRQ */
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	desc->chip->ack(irq);
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check why this interrupt was generated */
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req = locomo_readl(mapbase + LOCOMO_ICR) & 0x0f00;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (req) {
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* generate the next interrupt(s) */
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irq = LOCOMO_IRQ_START;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + irq;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 3; i++, d++, irq++) {
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (req & (0x0100 << i)) {
1870cd61b68c340a4f901a06e8bb5e0dea4353161c0Linus Torvalds				desc_handle_irq(irq, d);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_ack_irq(unsigned int irq)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_mask_irq(unsigned int irq)
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20010dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_ICR);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0010 << (irq - LOCOMO_IRQ_START));
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_ICR);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_unmask_irq(unsigned int irq)
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20910dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_ICR);
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0010 << (irq - LOCOMO_IRQ_START));
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_ICR);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21638c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownellstatic struct irq_chip locomo_chip = {
21738c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownell	.name	= "LOCOMO",
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_ack_irq,
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_mask_irq,
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_unmask_irq,
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22310dd5ce28d78e2440e8fa1135d17e33399d75340Russell Kingstatic void locomo_key_handler(unsigned int irq, struct irq_desc *desc)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22510dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	struct irq_desc *d;
22610dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + LOCOMO_IRQ_KEY_START;
2300cd61b68c340a4f901a06e8bb5e0dea4353161c0Linus Torvalds		desc_handle_irq(LOCOMO_IRQ_KEY_START, d);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_ack_irq(unsigned int irq)
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
23610dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START));
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_mask_irq(unsigned int irq)
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24510dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START));
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_unmask_irq(unsigned int irq)
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25410dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START));
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26138c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownellstatic struct irq_chip locomo_key_chip = {
26238c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownell	.name	= "LOCOMO-key",
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_key_ack_irq,
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_key_mask_irq,
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_key_unmask_irq,
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26810dd5ce28d78e2440e8fa1135d17e33399d75340Russell Kingstatic void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc)
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int req, i;
27110dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	struct irq_desc *d;
27210dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req = 	locomo_readl(mapbase + LOCOMO_GIR) &
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_readl(mapbase + LOCOMO_GPD) &
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (req) {
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irq = LOCOMO_IRQ_GPIO_START;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + LOCOMO_IRQ_GPIO_START;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 15; i++, irq++, d++) {
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (req & (0x0001 << i)) {
2830cd61b68c340a4f901a06e8bb5e0dea4353161c0Linus Torvalds				desc_handle_irq(irq, d);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_ack_irq(unsigned int irq)
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29110dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GWE);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GWE);
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GIS);
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GIS);
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GWE);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GWE);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_mask_irq(unsigned int irq)
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30810dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GIE);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GIE);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_unmask_irq(unsigned int irq)
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31710dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GIE);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GIE);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3242a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunzestatic int GPIO_IRQ_rising_edge;
3252a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunzestatic int GPIO_IRQ_falling_edge;
3262a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze
3272a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunzestatic int locomo_gpio_type(unsigned int irq, unsigned int type)
3282a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze{
3292a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	unsigned int mask;
3302a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	void __iomem *mapbase = get_irq_chip_data(irq);
3312a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze
3322a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	mask = 1 << (irq - LOCOMO_IRQ_GPIO_START);
3332a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze
3346cab48602996cdbcb277375a8107d53e21e8c9b9Dmitry Eremin-Solenikov	if (type == IRQ_TYPE_PROBE) {
3352a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
3362a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze			return 0;
3376cab48602996cdbcb277375a8107d53e21e8c9b9Dmitry Eremin-Solenikov		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
3382a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	}
3392a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze
3406cab48602996cdbcb277375a8107d53e21e8c9b9Dmitry Eremin-Solenikov	if (type & IRQ_TYPE_EDGE_RISING)
3412a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze		GPIO_IRQ_rising_edge |= mask;
3422a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	else
3432a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze		GPIO_IRQ_rising_edge &= ~mask;
3446cab48602996cdbcb277375a8107d53e21e8c9b9Dmitry Eremin-Solenikov	if (type & IRQ_TYPE_EDGE_FALLING)
3452a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze		GPIO_IRQ_falling_edge |= mask;
3462a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	else
3472a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze		GPIO_IRQ_falling_edge &= ~mask;
3482a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	locomo_writel(GPIO_IRQ_rising_edge, mapbase + LOCOMO_GRIE);
3492a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	locomo_writel(GPIO_IRQ_falling_edge, mapbase + LOCOMO_GFIE);
3502a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze
3512a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	return 0;
3522a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze}
3532a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze
35438c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownellstatic struct irq_chip locomo_gpio_chip = {
3552a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	.name	  = "LOCOMO-gpio",
3562a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	.ack	  = locomo_gpio_ack_irq,
3572a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	.mask	  = locomo_gpio_mask_irq,
3582a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	.unmask	  = locomo_gpio_unmask_irq,
3592a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	.set_type = locomo_gpio_type,
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36210dd5ce28d78e2440e8fa1135d17e33399d75340Russell Kingstatic void locomo_lt_handler(unsigned int irq, struct irq_desc *desc)
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
36410dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	struct irq_desc *d;
36510dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + LOCOMO_IRQ_LT_START;
3690cd61b68c340a4f901a06e8bb5e0dea4353161c0Linus Torvalds		desc_handle_irq(LOCOMO_IRQ_LT_START, d);
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_ack_irq(unsigned int irq)
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
37510dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_LTINT);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START));
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_LTINT);
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_mask_irq(unsigned int irq)
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
38410dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_LTINT);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START));
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_LTINT);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_unmask_irq(unsigned int irq)
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39310dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_LTINT);
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START));
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_LTINT);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40038c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownellstatic struct irq_chip locomo_lt_chip = {
40138c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownell	.name	= "LOCOMO-lt",
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_lt_ack_irq,
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_lt_mask_irq,
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_lt_unmask_irq,
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40710dd5ce28d78e2440e8fa1135d17e33399d75340Russell Kingstatic void locomo_spi_handler(unsigned int irq, struct irq_desc *desc)
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int req, i;
41010dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	struct irq_desc *d;
41110dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
413a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (req) {
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irq = LOCOMO_IRQ_SPI_START;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + irq;
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 3; i++, irq++, d++) {
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (req & (0x0001 << i)) {
4200cd61b68c340a4f901a06e8bb5e0dea4353161c0Linus Torvalds				desc_handle_irq(irq, d);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_ack_irq(unsigned int irq)
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
42810dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
430a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
432a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
434a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
436a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
438a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
440a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_mask_irq(unsigned int irq)
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
44510dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
447a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
449a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_unmask_irq(unsigned int irq)
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
45410dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	void __iomem *mapbase = get_irq_chip_data(irq);
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
456a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
458a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46138c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownellstatic struct irq_chip locomo_spi_chip = {
46238c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownell	.name	= "LOCOMO-spi",
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_spi_ack_irq,
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_spi_mask_irq,
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_spi_unmask_irq,
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_setup_irq(struct locomo *lchip)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int irq;
471548153663bbf33ca7c244a6bbddd82c26a17c331Russell King	void __iomem *irqbase = lchip->base;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Install handler for IRQ_LOCOMO_HW.
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4766cab48602996cdbcb277375a8107d53e21e8c9b9Dmitry Eremin-Solenikov	set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
47710dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_chip_data(lchip->irq, irqbase);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(lchip->irq, locomo_handler);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Install handlers for IRQ_LOCOMO_*_BASE */
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip);
48210dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase);
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip);
48610dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip);
49010dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip);
49410dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_chip_data(IRQ_LOCOMO_SPI_BASE, irqbase);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip);
49910dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_chip_data(LOCOMO_IRQ_KEY_START, irqbase);
50010dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_handler(LOCOMO_IRQ_KEY_START, handle_edge_irq);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) {
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_chip(irq, &locomo_gpio_chip);
50610dd5ce28d78e2440e8fa1135d17e33399d75340Russell King		set_irq_chip_data(irq, irqbase);
50710dd5ce28d78e2440e8fa1135d17e33399d75340Russell King		set_irq_handler(irq, handle_edge_irq);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip);
51310dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_chip_data(LOCOMO_IRQ_LT_START, irqbase);
51410dd5ce28d78e2440e8fa1135d17e33399d75340Russell King	set_irq_handler(LOCOMO_IRQ_LT_START, handle_edge_irq);
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */
5182a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 4; irq++) {
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_chip(irq, &locomo_spi_chip);
52010dd5ce28d78e2440e8fa1135d17e33399d75340Russell King		set_irq_chip_data(irq, irqbase);
52110dd5ce28d78e2440e8fa1135d17e33399d75340Russell King		set_irq_handler(irq, handle_edge_irq);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_dev_release(struct device *_dev)
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *dev = LOCOMO_DEV(_dev);
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(dev);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslocomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *dev;
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
540d2a02b93cf78205dd23226efb66481569900976eRussell King	dev = kzalloc(sizeof(struct locomo_dev), GFP_KERNEL);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev) {
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the parent device has a DMA mask associated with it,
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * propagate it down to the children.
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lchip->dev->dma_mask) {
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->dma_mask = *lchip->dev->dma_mask;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->dev.dma_mask = &dev->dma_mask;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5553f9787046ea37a26170dc4439efa21f8d23a9978Kay Sievers	dev_set_name(&dev->dev, "%s", info->name);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->devid	 = info->devid;
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.parent  = lchip->dev;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.bus     = &locomo_bus_type;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.release = locomo_dev_release;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.coherent_dma_mask = lchip->dev->coherent_dma_mask;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (info->offset)
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->mapbase = lchip->base + info->offset;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->mapbase = 0;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->length = info->length;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memmove(dev->irq, info->irq, sizeof(dev->irq));
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = device_register(&dev->dev);
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret) {
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(dev);
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
578b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#ifdef CONFIG_PM
579b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
580b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenzstruct locomo_save_data {
581b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_GPO;
582b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_SPICT;
583b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_GPE;
584b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_ASD;
585b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_SPIMD;
586b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz};
587b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
5883ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_suspend(struct platform_device *dev, pm_message_t state)
589b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz{
5903ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	struct locomo *lchip = platform_get_drvdata(dev);
591b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	struct locomo_save_data *save;
592b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	unsigned long flags;
593b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
594b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
595b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	if (!save)
596b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		return -ENOMEM;
597b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
59893160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki	lchip->saved_state = save;
599b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
600b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	spin_lock_irqsave(&lchip->lock, flags);
601b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
602b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save->LCM_GPO     = locomo_readl(lchip->base + LOCOMO_GPO);	/* GPIO */
603b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_GPO);
6042a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	save->LCM_SPICT   = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT);	/* SPI */
605b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x40, lchip->base + LOCOMO_SPICT);
606b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save->LCM_GPE     = locomo_readl(lchip->base + LOCOMO_GPE);	/* GPIO */
607b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_GPE);
608b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save->LCM_ASD     = locomo_readl(lchip->base + LOCOMO_ASD);	/* ADSTART */
609b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_ASD);
6102a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	save->LCM_SPIMD   = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPIMD);	/* SPI */
6112a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	locomo_writel(0x3C14, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD);
612b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
613b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_PAIF);
614b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_DAC);
615b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC);
616b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
6172a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	if ((locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88))
618b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		locomo_writel(0x00, lchip->base + LOCOMO_C32K); 	/* CLK32 off */
619b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	else
620b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		/* 18MHz already enabled, so no wait */
621b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		locomo_writel(0xc1, lchip->base + LOCOMO_C32K); 	/* CLK32 on */
622b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
623b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_TADC);		/* 18MHz clock off*/
624b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC);			/* 22MHz/24MHz clock off */
625b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);			/* FL */
626b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
627b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	spin_unlock_irqrestore(&lchip->lock, flags);
628b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
629b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	return 0;
630b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz}
631b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
6323ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_resume(struct platform_device *dev)
633b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz{
6343ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	struct locomo *lchip = platform_get_drvdata(dev);
635b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	struct locomo_save_data *save;
636b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	unsigned long r;
637b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	unsigned long flags;
63893160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki
63993160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki	save = lchip->saved_state;
640b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	if (!save)
641b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		return 0;
642b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
643b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	spin_lock_irqsave(&lchip->lock, flags);
644b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
645b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO);
6462a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPI + LOCOMO_SPICT);
647b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE);
648b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD);
6492a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD);
650b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
651b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_C32K);
652b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x90, lchip->base + LOCOMO_TADC);
653b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
654b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC);
655b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
656b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	r &= 0xFEFF;
657b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
658b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
659b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
660b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	spin_unlock_irqrestore(&lchip->lock, flags);
66193160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki
66293160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki	lchip->saved_state = NULL;
663b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	kfree(save);
664b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
665b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	return 0;
666b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz}
667b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#endif
668b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
6694ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	locomo_probe - probe for a single LoCoMo chip.
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@phys_addr: physical address of device.
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Probe for a LoCoMo chip.  This must be called
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	before any other locomo-specific code.
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Returns:
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	%-ENODEV	device not found.
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	%-EBUSY		physical address already marked in-use.
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	%0		successful.
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__locomo_probe(struct device *me, struct resource *mem, int irq)
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo *lchip;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long r;
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, ret = -ENODEV;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
689d2a02b93cf78205dd23226efb66481569900976eRussell King	lchip = kzalloc(sizeof(struct locomo), GFP_KERNEL);
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!lchip)
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&lchip->lock);
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip->dev = me;
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_set_drvdata(lchip->dev, lchip);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip->phys = mem->start;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip->irq = irq;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Map the whole region.  This also maps the
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * registers for our children.
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip->base = ioremap(mem->start, PAGE_SIZE);
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!lchip->base) {
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* locomo initialize */
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_ICR);
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* KEYBOARD */
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* GPIO */
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_GPO);
7182a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14))
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			, lchip->base + LOCOMO_GPE);
7202a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14))
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			, lchip->base + LOCOMO_GPD);
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_GIE);
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
724e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	/* Frontlight */
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
7274ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Longtime timer */
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_LTINT);
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* SPI */
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_SPIIE);
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD);
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_ASD);
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= 0x8000;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_ASD);
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(6 + 8 + 320 + 30 - 10 - 128 + 4, lchip->base + LOCOMO_HSD);
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_HSD);
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= 0x8000;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_HSD);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(128 / 8, lchip->base + LOCOMO_HSC);
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* XON */
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0x80, lchip->base + LOCOMO_TADC);
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(1000);
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* CLK9MEN */
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_TADC);
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= 0x10;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_TADC);
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(100);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* init DAC */
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_DAC);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_DAC);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_VER);
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "LoCoMo Chip: %lu%lu\n", (r >> 8), (r & 0xff));
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The interrupt controller must be initialised before any
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * other device to ensure that the interrupts are available.
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lchip->irq != NO_IRQ)
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_setup_irq(lchip);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < ARRAY_SIZE(locomo_devices); i++)
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_init_one_child(lchip, &locomo_devices[i]);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(lchip);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
778e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic int locomo_remove_child(struct device *dev, void *data)
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
780e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek	device_unregister(dev);
781e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek	return 0;
782e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek}
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
784e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic void __locomo_remove(struct locomo *lchip)
785e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek{
786e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek	device_for_each_child(lchip->dev, NULL, locomo_remove_child);
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lchip->irq != NO_IRQ) {
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_chained_handler(lchip->irq, NULL);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_data(lchip->irq, NULL);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(lchip->base);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(lchip);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7973ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_probe(struct platform_device *dev)
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *mem;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int irq;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8023ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!mem)
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
8053ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	irq = platform_get_irq(dev, 0);
806489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel	if (irq < 0)
807489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel		return -ENXIO;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8093ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	return __locomo_probe(&dev->dev, mem, irq);
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8123ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_remove(struct platform_device *dev)
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
814c35bf4a593631850ab437b37ddcded4e05548e9ePavel Machek	struct locomo *lchip = platform_get_drvdata(dev);
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lchip) {
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__locomo_remove(lchip);
8183ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King		platform_set_drvdata(dev, NULL);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Not sure if this should be on the system bus or not yet.
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	We really want some way to register a system device at
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	the per-machine level, and then have this driver pick
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	up the registered devices.
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8303ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver locomo_device_driver = {
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= locomo_probe,
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= locomo_remove,
833b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#ifdef CONFIG_PM
834b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	.suspend	= locomo_suspend,
835b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	.resume		= locomo_resume,
836b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#endif
8373ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	.driver		= {
8383ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King		.name	= "locomo",
8393ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	},
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Get the parent device driver (us) structure
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	from a child function device
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct locomo *locomo_chip_driver(struct locomo_dev *ldev)
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (struct locomo *)dev_get_drvdata(ldev->dev.parent);
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8518d48427ecb0639593ccf14e807479b7873254ccbRichard Purdievoid locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir)
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8538d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie	struct locomo *lchip = dev_get_drvdata(dev);
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8578d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie	if (!lchip)
8588d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie		return;
8598d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_GPD);
8632a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	if (dir)
8642a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze		r |= bits;
8652a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze	else
8662a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze		r &= ~bits;
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_GPD);
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_GPE);
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dir)
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r |= bits;
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r &= ~bits;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_GPE);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8798d48427ecb0639593ccf14e807479b7873254ccbRichard Purdieint locomo_gpio_read_level(struct device *dev, unsigned int bits)
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8818d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie	struct locomo *lchip = dev_get_drvdata(dev);
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8858d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie	if (!lchip)
8868d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie		return -ENODEV;
8878d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = locomo_readl(lchip->base + LOCOMO_GPL);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret &= bits;
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8968d48427ecb0639593ccf14e807479b7873254ccbRichard Purdieint locomo_gpio_read_output(struct device *dev, unsigned int bits)
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8988d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie	struct locomo *lchip = dev_get_drvdata(dev);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret;
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9028d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie	if (!lchip)
9038d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie		return -ENODEV;
9048d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = locomo_readl(lchip->base + LOCOMO_GPO);
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret &= bits;
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9138d48427ecb0639593ccf14e807479b7873254ccbRichard Purdievoid locomo_gpio_write(struct device *dev, unsigned int bits, unsigned int set)
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9158d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie	struct locomo *lchip = dev_get_drvdata(dev);
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9198d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie	if (!lchip)
9208d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie		return;
9218d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_GPO);
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (set)
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r |= bits;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r &= ~bits;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_GPO);
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_m62332_sendbit(void *mapbase, int bit)
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_DATA_HOLD_TIME);	/* 300 nsec */
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bit & 1) {
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r = locomo_readl(mapbase + LOCOMO_DAC);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r |=  LOCOMO_DAC_SDAOEB;
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_writel(r, mapbase + LOCOMO_DAC);
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r = locomo_readl(mapbase + LOCOMO_DAC);
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r &=  ~(LOCOMO_DAC_SDAOEB);
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_writel(r, mapbase + LOCOMO_DAC);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_DATA_SETUP_TIME);	/* 250 nsec */
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/*  4.0 usec */
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel)
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo *lchip = locomo_chip_driver(ldev);
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char data;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = lchip->base;
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start */
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_BUS_FREE_TIME);	/* 5.0 usec */
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.0 usec */
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SDAOEB);
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_START_HOLD_TIME);	/* 5.0 usec */
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_DATA_HOLD_TIME);	/* 300 nsec */
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Send slave address and W bit (LSB is W bit) */
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data = (M62332_SLAVE_ADDR << 1) | M62332_W_BIT;
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 8; i++) {
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_m62332_sendbit(mapbase, data >> (8 - i));
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check A bit */
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SDAOEB);
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "locomo: m62332_senddata Error 1\n");
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Send Sub address (LSB is channel select) */
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*    channel = 0 : ch1 select              */
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*            = 1 : ch2 select              */
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data = M62332_SUB_ADDR + channel;
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 8; i++) {
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_m62332_sendbit(mapbase, data >> (8 - i));
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check A bit */
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SDAOEB);
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "locomo: m62332_senddata Error 2\n");
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Send DAC data */
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 8; i++) {
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_m62332_sendbit(mapbase, dac_data >> (8 - i));
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check A bit */
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SDAOEB);
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "locomo: m62332_senddata Error 3\n");
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* stop */
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4 usec */
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SDAOEB;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4 usec */
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 1000 nsec */
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1099e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie *	Frontlight control
1100e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie */
1101e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie
1102e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdiestatic struct locomo *locomo_chip_driver(struct locomo_dev *ldev);
1103e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie
1104e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdievoid locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf)
1105e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie{
1106e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	unsigned long flags;
1107e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	struct locomo *lchip = locomo_chip_driver(dev);
1108e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie
1109e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	if (vr)
11108d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie		locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 1);
1111e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	else
11128d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie		locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 0);
1113e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie
1114e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	spin_lock_irqsave(&lchip->lock, flags);
1115e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
1116e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	udelay(100);
1117e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
1118e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
1119e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie	spin_unlock_irqrestore(&lchip->lock, flags);
1120e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie}
1121e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie
1122e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie/*
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	LoCoMo "Register Access Bus."
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	We model this as a regular bus type, and hang devices directly
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	off this.
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_match(struct device *_dev, struct device_driver *_drv)
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *dev = LOCOMO_DEV(_dev);
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(_drv);
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev->devid == drv->devid;
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_suspend(struct device *dev, pm_message_t state)
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *ldev = LOCOMO_DEV(dev);
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->suspend)
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = drv->suspend(ldev, state);
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_resume(struct device *dev)
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *ldev = LOCOMO_DEV(dev);
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->resume)
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = drv->resume(ldev);
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_probe(struct device *dev)
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *ldev = LOCOMO_DEV(dev);
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = -ENODEV;
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv->probe)
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = drv->probe(ldev);
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_remove(struct device *dev)
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *ldev = LOCOMO_DEV(dev);
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv->remove)
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = drv->remove(ldev);
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type locomo_bus_type = {
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "locomo-bus",
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.match		= locomo_match,
1183306955be37dd1b1f232f19766227ccccb83f7873Russell King	.probe		= locomo_bus_probe,
1184306955be37dd1b1f232f19766227ccccb83f7873Russell King	.remove		= locomo_bus_remove,
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= locomo_bus_suspend,
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= locomo_bus_resume,
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint locomo_driver_register(struct locomo_driver *driver)
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver->drv.bus = &locomo_bus_type;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return driver_register(&driver->drv);
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_driver_unregister(struct locomo_driver *driver)
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver_unregister(&driver->drv);
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init locomo_init(void)
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = bus_register(&locomo_bus_type);
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret == 0)
12043ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King		platform_driver_register(&locomo_device_driver);
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit locomo_exit(void)
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12103ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	platform_driver_unregister(&locomo_device_driver);
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bus_unregister(&locomo_bus_type);
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(locomo_init);
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(locomo_exit);
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Sharp LoCoMo core driver");
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_driver_register);
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_driver_unregister);
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_set_dir);
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_read_level);
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_read_output);
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_write);
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_m62332_senddata);
1228