locomo.c revision 489447380a2921ec0e9154f773c44ab3167ede4b
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/config.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
25d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hardware.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mach/irq.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hardware/locomo.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* M62332 output channel selection */
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_EVR_CH	1	/* M62332 volume channel number  */
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*   0 : CH.1 , 1 : CH. 2        */
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DAC send data */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	M62332_SLAVE_ADDR	0x4e	/* Slave address  */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	M62332_W_BIT		0x00	/* W bit (0 only) */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	M62332_SUB_ADDR		0x00	/* Sub address    */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	M62332_A_BIT		0x00	/* A bit (0 only) */
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DAC setup and hold times (expressed in us) */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_BUS_FREE_TIME	5	/*   4.7 us */
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_START_SETUP_TIME	5	/*   4.7 us */
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_STOP_SETUP_TIME	4	/*   4.0 us */
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_START_HOLD_TIME	5	/*   4.7 us */
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_SCL_LOW_HOLD_TIME	5	/*   4.7 us */
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_SCL_HIGH_HOLD_TIME	4	/*   4.0 us */
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_DATA_SETUP_TIME	1	/*   250 ns */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_DATA_HOLD_TIME	1	/*   300 ns */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_LOW_SETUP_TIME	1	/*   300 ns */
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_HIGH_SETUP_TIME	1	/*  1000 ns */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the following is the overall data for the locomo chip */
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct locomo {
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device *dev;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long phys;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int irq;
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t lock;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *base;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct locomo_dev_info {
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	offset;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long	length;
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	devid;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	irq[1];
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *	name;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* All the locomo devices.  If offset is non-zero, the mapbase for the
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locomo_dev will be set to the chip base plus offset.  If offset is
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zero, then the mapbase for the locomo_dev will be set to zero.  An
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * offset of zero means the device only uses GPIOs or other helper
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * functions inside this file */
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct locomo_dev_info locomo_devices[] = {
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid 		= LOCOMO_DEVID_KEYBOARD,
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq = {
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			IRQ_LOCOMO_KEY,
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-keyboard",
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_KEYBOARD,
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 16,
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_FRONTLIGHT,
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq		= {},
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-frontlight",
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_FRONTLIGHT,
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 8,
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_BACKLIGHT,
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq		= {},
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-backlight",
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_BACKLIGHT,
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 8,
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_AUDIO,
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq		= {},
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-audio",
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_AUDIO,
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 4,
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_LED,
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq 		= {},
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-led",
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= LOCOMO_LED,
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 8,
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.devid		= LOCOMO_DEVID_UART,
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.irq		= {},
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name		= "locomo-uart",
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.offset		= 0,
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.length		= 0,
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** LoCoMo interrupt handling stuff.
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: LoCoMo has a 1 to many mapping on all of its IRQs.
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that is, there is only one real hardware interrupt
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we determine which interrupt it is by reading some IO memory.
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We have two levels of expansion, first in the handler for the
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hardware interrupt we generate an interrupt
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_*_BASE and those handlers generate more interrupts
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hardware irq reads LOCOMO_ICR & 0x0f00
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_KEY_BASE
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_GPIO_BASE
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_LT_BASE
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_BASE
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_KEY_BASE reads LOCOMO_KIC & 0x0001
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_KEY
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_GPIO_BASE reads LOCOMO_GIR & LOCOMO_GPD & 0xffff
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_GPIO[0-15]
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_LT_BASE reads LOCOMO_LTINT & 0x0001
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_LT
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_SPI_BASE reads LOCOMO_SPIIR & 0x000F
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_RFR
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_RFW
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_OVRN
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   IRQ_LOCOMO_SPI_TEND
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_START	(IRQ_LOCOMO_KEY_BASE)
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_KEY_START	(IRQ_LOCOMO_KEY)
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LOCOMO_IRQ_GPIO_START	(IRQ_LOCOMO_GPIO0)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LOCOMO_IRQ_LT_START	(IRQ_LOCOMO_LT)
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LOCOMO_IRQ_SPI_START	(IRQ_LOCOMO_SPI_RFR)
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_handler(unsigned int irq, struct irqdesc *desc,
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct pt_regs *regs)
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int req, i;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct irqdesc *d;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Acknowledge the parent IRQ */
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	desc->chip->ack(irq);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check why this interrupt was generated */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req = locomo_readl(mapbase + LOCOMO_ICR) & 0x0f00;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (req) {
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* generate the next interrupt(s) */
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irq = LOCOMO_IRQ_START;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + irq;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 3; i++, d++, irq++) {
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (req & (0x0100 << i)) {
179664399e1fbdceb18da9c9c5534dedd62327c63e8Russell King				desc_handle_irq(irq, d, regs);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_ack_irq(unsigned int irq)
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_mask_irq(unsigned int irq)
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_ICR);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0010 << (irq - LOCOMO_IRQ_START));
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_ICR);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_unmask_irq(unsigned int irq)
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_ICR);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0010 << (irq - LOCOMO_IRQ_START));
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_ICR);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_chip = {
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_ack_irq,
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_mask_irq,
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_unmask_irq,
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_handler(unsigned int irq, struct irqdesc *desc,
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    struct pt_regs *regs)
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct irqdesc *d;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + LOCOMO_IRQ_KEY_START;
222664399e1fbdceb18da9c9c5534dedd62327c63e8Russell King		desc_handle_irq(LOCOMO_IRQ_KEY_START, d, regs);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_ack_irq(unsigned int irq)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START));
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_mask_irq(unsigned int irq)
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START));
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_unmask_irq(unsigned int irq)
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START));
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_key_chip = {
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_key_ack_irq,
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_key_mask_irq,
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_key_unmask_irq,
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc,
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     struct pt_regs *regs)
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int req, i;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct irqdesc *d;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req = 	locomo_readl(mapbase + LOCOMO_GIR) &
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_readl(mapbase + LOCOMO_GPD) &
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (req) {
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irq = LOCOMO_IRQ_GPIO_START;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + LOCOMO_IRQ_GPIO_START;
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 15; i++, irq++, d++) {
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (req & (0x0001 << i)) {
275664399e1fbdceb18da9c9c5534dedd62327c63e8Russell King				desc_handle_irq(irq, d, regs);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_ack_irq(unsigned int irq)
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GWE);
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GWE);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GIS);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GIS);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
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
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_mask_irq(unsigned int irq)
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GIE);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GIE);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_unmask_irq(unsigned int irq)
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_GIE);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_GIE);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_gpio_chip = {
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_gpio_ack_irq,
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_gpio_mask_irq,
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_gpio_unmask_irq,
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_handler(unsigned int irq, struct irqdesc *desc,
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   struct pt_regs *regs)
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct irqdesc *d;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + LOCOMO_IRQ_LT_START;
330664399e1fbdceb18da9c9c5534dedd62327c63e8Russell King		desc_handle_irq(LOCOMO_IRQ_LT_START, d, regs);
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_ack_irq(unsigned int irq)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_LTINT);
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START));
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_LTINT);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_mask_irq(unsigned int irq)
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_LTINT);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START));
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_LTINT);
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_unmask_irq(unsigned int irq)
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_LTINT);
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START));
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_LTINT);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_lt_chip = {
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_lt_ack_irq,
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_lt_mask_irq,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_lt_unmask_irq,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_handler(unsigned int irq, struct irqdesc *desc,
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    struct pt_regs *regs)
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int req, i;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct irqdesc *d;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	req = locomo_readl(mapbase + LOCOMO_SPIIR) & 0x000F;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (req) {
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irq = LOCOMO_IRQ_SPI_START;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d = irq_desc + irq;
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 3; i++, irq++, d++) {
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (req & (0x0001 << i)) {
381664399e1fbdceb18da9c9c5534dedd62327c63e8Russell King				desc_handle_irq(irq, d, regs);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_ack_irq(unsigned int irq)
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_SPIWE);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_SPIWE);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_SPIIS);
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_SPIIS);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_SPIWE);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_SPIWE);
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_mask_irq(unsigned int irq)
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_SPIIE);
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_SPIIE);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_unmask_irq(unsigned int irq)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = get_irq_chipdata(irq);
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_SPIIE);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_SPIIE);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_spi_chip = {
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ack	= locomo_spi_ack_irq,
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mask	= locomo_spi_mask_irq,
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.unmask	= locomo_spi_unmask_irq,
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_setup_irq(struct locomo *lchip)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int irq;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *irqbase = lchip->base;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Install handler for IRQ_LOCOMO_HW.
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_type(lchip->irq, IRQT_FALLING);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chipdata(lchip->irq, irqbase);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(lchip->irq, locomo_handler);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Install handlers for IRQ_LOCOMO_*_BASE */
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chipdata(IRQ_LOCOMO_KEY_BASE, irqbase);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_flags(IRQ_LOCOMO_KEY_BASE, IRQF_VALID | IRQF_PROBE);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip);
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chipdata(IRQ_LOCOMO_GPIO_BASE, irqbase);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_flags(IRQ_LOCOMO_GPIO_BASE, IRQF_VALID | IRQF_PROBE);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chipdata(IRQ_LOCOMO_LT_BASE, irqbase);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_flags(IRQ_LOCOMO_LT_BASE, IRQF_VALID | IRQF_PROBE);
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chipdata(IRQ_LOCOMO_SPI_BASE, irqbase);
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler);
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_flags(IRQ_LOCOMO_SPI_BASE, IRQF_VALID | IRQF_PROBE);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip);
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chipdata(LOCOMO_IRQ_KEY_START, irqbase);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_handler(LOCOMO_IRQ_KEY_START, do_edge_IRQ);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) {
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_chip(irq, &locomo_gpio_chip);
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_chipdata(irq, irqbase);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_handler(irq, do_edge_IRQ);
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip);
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_chipdata(LOCOMO_IRQ_LT_START, irqbase);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_handler(LOCOMO_IRQ_LT_START, do_edge_IRQ);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE);
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 3; irq++) {
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_chip(irq, &locomo_spi_chip);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_chipdata(irq, irqbase);
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_handler(irq, do_edge_IRQ);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_dev_release(struct device *_dev)
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *dev = LOCOMO_DEV(_dev);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(dev);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslocomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *dev;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev = kmalloc(sizeof(struct locomo_dev), GFP_KERNEL);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev) {
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(dev, 0, sizeof(struct locomo_dev));
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strncpy(dev->dev.bus_id,info->name,sizeof(dev->dev.bus_id));
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the parent device has a DMA mask associated with it,
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * propagate it down to the children.
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lchip->dev->dma_mask) {
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->dma_mask = *lchip->dev->dma_mask;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->dev.dma_mask = &dev->dma_mask;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->devid	 = info->devid;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.parent  = lchip->dev;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.bus     = &locomo_bus_type;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.release = locomo_dev_release;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.coherent_dma_mask = lchip->dev->coherent_dma_mask;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (info->offset)
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->mapbase = lchip->base + info->offset;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->mapbase = 0;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->length = info->length;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memmove(dev->irq, info->irq, sizeof(dev->irq));
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = device_register(&dev->dev);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret) {
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(dev);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
543b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#ifdef CONFIG_PM
544b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
545b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenzstruct locomo_save_data {
546b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_GPO;
547b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_SPICT;
548b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_GPE;
549b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_ASD;
550b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	u16	LCM_SPIMD;
551b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz};
552b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
5533ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_suspend(struct platform_device *dev, pm_message_t state)
554b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz{
5553ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	struct locomo *lchip = platform_get_drvdata(dev);
556b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	struct locomo_save_data *save;
557b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	unsigned long flags;
558b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
559b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
560b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	if (!save)
561b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		return -ENOMEM;
562b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
5633ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	dev->dev.power.saved_state = (void *) save;
564b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
565b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	spin_lock_irqsave(&lchip->lock, flags);
566b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
567b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save->LCM_GPO     = locomo_readl(lchip->base + LOCOMO_GPO);	/* GPIO */
568b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_GPO);
569b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save->LCM_SPICT   = locomo_readl(lchip->base + LOCOMO_SPICT);	/* SPI */
570b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x40, lchip->base + LOCOMO_SPICT);
571b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save->LCM_GPE     = locomo_readl(lchip->base + LOCOMO_GPE);	/* GPIO */
572b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_GPE);
573b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save->LCM_ASD     = locomo_readl(lchip->base + LOCOMO_ASD);	/* ADSTART */
574b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_ASD);
575b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	save->LCM_SPIMD   = locomo_readl(lchip->base + LOCOMO_SPIMD);	/* SPI */
576b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x3C14, lchip->base + LOCOMO_SPIMD);
577b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
578b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_PAIF);
579b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_DAC);
580b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC);
581b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
582b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	if ( (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88) )
583b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		locomo_writel(0x00, lchip->base + LOCOMO_C32K); 	/* CLK32 off */
584b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	else
585b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		/* 18MHz already enabled, so no wait */
586b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		locomo_writel(0xc1, lchip->base + LOCOMO_C32K); 	/* CLK32 on */
587b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
588b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_TADC);		/* 18MHz clock off*/
589b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC);			/* 22MHz/24MHz clock off */
590b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);			/* FL */
591b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
592b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	spin_unlock_irqrestore(&lchip->lock, flags);
593b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
594b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	return 0;
595b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz}
596b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
5973ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_resume(struct platform_device *dev)
598b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz{
5993ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	struct locomo *lchip = platform_get_drvdata(dev);
600b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	struct locomo_save_data *save;
601b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	unsigned long r;
602b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	unsigned long flags;
603b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
6043ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	save = (struct locomo_save_data *) dev->dev.power.saved_state;
605b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	if (!save)
606b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz		return 0;
607b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
608b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	spin_lock_irqsave(&lchip->lock, flags);
609b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
610b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO);
611b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPICT);
612b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE);
613b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD);
614b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPIMD);
615b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
616b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x00, lchip->base + LOCOMO_C32K);
617b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x90, lchip->base + LOCOMO_TADC);
618b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
619b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC);
620b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
621b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	r &= 0xFEFF;
622b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
623b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
624b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
625b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	spin_unlock_irqrestore(&lchip->lock, flags);
626b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	kfree(save);
627b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
628b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	return 0;
629b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz}
630b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#endif
631b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz
6324ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
6334ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek#define LCM_ALC_EN	0x8000
6344ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
6354ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machekvoid frontlight_set(struct locomo *lchip, int duty, int vr, int bpwf)
6364ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek{
6374ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	unsigned long flags;
6384ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
6394ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	spin_lock_irqsave(&lchip->lock, flags);
6404ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
6414ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	udelay(100);
6424ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
6434ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	locomo_writel(bpwf | LCM_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
6444ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	spin_unlock_irqrestore(&lchip->lock, flags);
6454ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek}
6464ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
6474ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	locomo_probe - probe for a single LoCoMo chip.
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@phys_addr: physical address of device.
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Probe for a LoCoMo chip.  This must be called
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	before any other locomo-specific code.
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Returns:
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	%-ENODEV	device not found.
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	%-EBUSY		physical address already marked in-use.
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	%0		successful.
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__locomo_probe(struct device *me, struct resource *mem, int irq)
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo *lchip;
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long r;
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, ret = -ENODEV;
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip = kmalloc(sizeof(struct locomo), GFP_KERNEL);
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!lchip)
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(lchip, 0, sizeof(struct locomo));
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&lchip->lock);
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip->dev = me;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_set_drvdata(lchip->dev, lchip);
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip->phys = mem->start;
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip->irq = irq;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Map the whole region.  This also maps the
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * registers for our children.
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lchip->base = ioremap(mem->start, PAGE_SIZE);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!lchip->base) {
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* locomo initialize */
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_ICR);
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* KEYBOARD */
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* GPIO */
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_GPO);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel( (LOCOMO_GPIO(2) | LOCOMO_GPIO(3) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14))
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			, lchip->base + LOCOMO_GPE);
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel( (LOCOMO_GPIO(2) | LOCOMO_GPIO(3) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14))
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			, lchip->base + LOCOMO_GPD);
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_GIE);
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* FrontLight */
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
7074ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
7084ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	/* Same constants can be used for collie and poodle
7094ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	   (depending on CONFIG options in original sharp code)? */
7104ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek	frontlight_set(lchip, 163, 0, 148);
7114ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Longtime timer */
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_LTINT);
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* SPI */
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0, lchip->base + LOCOMO_SPIIE);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_ASD);
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= 0x8000;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_ASD);
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(6 + 8 + 320 + 30 - 10 - 128 + 4, lchip->base + LOCOMO_HSD);
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_HSD);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= 0x8000;
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_HSD);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(128 / 8, lchip->base + LOCOMO_HSC);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* XON */
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(0x80, lchip->base + LOCOMO_TADC);
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(1000);
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* CLK9MEN */
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_TADC);
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= 0x10;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_TADC);
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(100);
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* init DAC */
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_DAC);
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_DAC);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_VER);
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "LoCoMo Chip: %lu%lu\n", (r >> 8), (r & 0xff));
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The interrupt controller must be initialised before any
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * other device to ensure that the interrupts are available.
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lchip->irq != NO_IRQ)
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_setup_irq(lchip);
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < ARRAY_SIZE(locomo_devices); i++)
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_init_one_child(lchip, &locomo_devices[i]);
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(lchip);
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
763e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic int locomo_remove_child(struct device *dev, void *data)
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
765e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek	device_unregister(dev);
766e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek	return 0;
767e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek}
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
769e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic void __locomo_remove(struct locomo *lchip)
770e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek{
771e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek	device_for_each_child(lchip->dev, NULL, locomo_remove_child);
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lchip->irq != NO_IRQ) {
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_chained_handler(lchip->irq, NULL);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_irq_data(lchip->irq, NULL);
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(lchip->base);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(lchip);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7823ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_probe(struct platform_device *dev)
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *mem;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int irq;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7873ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!mem)
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
7903ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	irq = platform_get_irq(dev, 0);
791489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel	if (irq < 0)
792489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel		return -ENXIO;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7943ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	return __locomo_probe(&dev->dev, mem, irq);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7973ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_remove(struct platform_device *dev)
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
799c35bf4a593631850ab437b37ddcded4e05548e9ePavel Machek	struct locomo *lchip = platform_get_drvdata(dev);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lchip) {
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__locomo_remove(lchip);
8033ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King		platform_set_drvdata(dev, NULL);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Not sure if this should be on the system bus or not yet.
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	We really want some way to register a system device at
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	the per-machine level, and then have this driver pick
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	up the registered devices.
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8153ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver locomo_device_driver = {
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= locomo_probe,
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= locomo_remove,
818b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#ifdef CONFIG_PM
819b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	.suspend	= locomo_suspend,
820b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz	.resume		= locomo_resume,
821b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#endif
8223ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	.driver		= {
8233ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King		.name	= "locomo",
8243ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	},
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Get the parent device driver (us) structure
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	from a child function device
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct locomo *locomo_chip_driver(struct locomo_dev *ldev)
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (struct locomo *)dev_get_drvdata(ldev->dev.parent);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir)
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo *lchip = locomo_chip_driver(ldev);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_GPD);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &= ~bits;
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_GPD);
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_GPE);
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dir)
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r |= bits;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r &= ~bits;
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_GPE);
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits)
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo *lchip = locomo_chip_driver(ldev);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = locomo_readl(lchip->base + LOCOMO_GPL);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret &= bits;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits)
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo *lchip = locomo_chip_driver(ldev);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int ret;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = locomo_readl(lchip->base + LOCOMO_GPO);
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret &= bits;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set)
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo *lchip = locomo_chip_driver(ldev);
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(lchip->base + LOCOMO_GPO);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (set)
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r |= bits;
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r &= ~bits;
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, lchip->base + LOCOMO_GPO);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_m62332_sendbit(void *mapbase, int bit)
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_DATA_HOLD_TIME);	/* 300 nsec */
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bit & 1) {
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r = locomo_readl(mapbase + LOCOMO_DAC);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r |=  LOCOMO_DAC_SDAOEB;
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_writel(r, mapbase + LOCOMO_DAC);
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r = locomo_readl(mapbase + LOCOMO_DAC);
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r &=  ~(LOCOMO_DAC_SDAOEB);
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_writel(r, mapbase + LOCOMO_DAC);
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_DATA_SETUP_TIME);	/* 250 nsec */
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/*  4.0 usec */
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel)
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo *lchip = locomo_chip_driver(ldev);
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char data;
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int r;
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mapbase = lchip->base;
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lchip->lock, flags);
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start */
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_BUS_FREE_TIME);	/* 5.0 usec */
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.0 usec */
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SDAOEB);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_START_HOLD_TIME);	/* 5.0 usec */
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_DATA_HOLD_TIME);	/* 300 nsec */
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Send slave address and W bit (LSB is W bit) */
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data = (M62332_SLAVE_ADDR << 1) | M62332_W_BIT;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 8; i++) {
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_m62332_sendbit(mapbase, data >> (8 - i));
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check A bit */
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SDAOEB);
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "locomo: m62332_senddata Error 1\n");
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Send Sub address (LSB is channel select) */
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*    channel = 0 : ch1 select              */
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*            = 1 : ch2 select              */
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data = M62332_SUB_ADDR + channel;
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 8; i++) {
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_m62332_sendbit(mapbase, data >> (8 - i));
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check A bit */
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SDAOEB);
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "locomo: m62332_senddata Error 2\n");
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Send DAC data */
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 8; i++) {
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		locomo_m62332_sendbit(mapbase, dac_data >> (8 - i));
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check A bit */
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SDAOEB);
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "locomo: m62332_senddata Error 3\n");
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* stop */
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r &=  ~(LOCOMO_DAC_SCLOEB);
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB;
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4 usec */
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SDAOEB;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4 usec */
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = locomo_readl(mapbase + LOCOMO_DAC);
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r |=  LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	locomo_writel(r, mapbase + LOCOMO_DAC);
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_LOW_SETUP_TIME);	/* 1000 nsec */
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lchip->lock, flags);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	LoCoMo "Register Access Bus."
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	We model this as a regular bus type, and hang devices directly
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	off this.
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_match(struct device *_dev, struct device_driver *_drv)
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *dev = LOCOMO_DEV(_dev);
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(_drv);
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev->devid == drv->devid;
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_suspend(struct device *dev, pm_message_t state)
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *ldev = LOCOMO_DEV(dev);
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->suspend)
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = drv->suspend(ldev, state);
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_resume(struct device *dev)
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *ldev = LOCOMO_DEV(dev);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->resume)
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = drv->resume(ldev);
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_probe(struct device *dev)
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *ldev = LOCOMO_DEV(dev);
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = -ENODEV;
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv->probe)
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = drv->probe(ldev);
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_remove(struct device *dev)
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_dev *ldev = LOCOMO_DEV(dev);
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv->remove)
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = drv->remove(ldev);
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type locomo_bus_type = {
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "locomo-bus",
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.match		= locomo_match,
1129306955be37dd1b1f232f19766227ccccb83f7873Russell King	.probe		= locomo_bus_probe,
1130306955be37dd1b1f232f19766227ccccb83f7873Russell King	.remove		= locomo_bus_remove,
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= locomo_bus_suspend,
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= locomo_bus_resume,
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint locomo_driver_register(struct locomo_driver *driver)
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver->drv.bus = &locomo_bus_type;
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return driver_register(&driver->drv);
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_driver_unregister(struct locomo_driver *driver)
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver_unregister(&driver->drv);
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init locomo_init(void)
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = bus_register(&locomo_bus_type);
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret == 0)
11503ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King		platform_driver_register(&locomo_device_driver);
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit locomo_exit(void)
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11563ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King	platform_driver_unregister(&locomo_device_driver);
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bus_unregister(&locomo_bus_type);
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(locomo_init);
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(locomo_exit);
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Sharp LoCoMo core driver");
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_driver_register);
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_driver_unregister);
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_set_dir);
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_read_level);
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_read_output);
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_write);
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_m62332_senddata);
1174