locomo.c revision e24da5d316667a91b3a19b5761a211946ec649bb
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> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/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/mach-types.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mach/irq.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hardware/locomo.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* M62332 output channel selection */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_EVR_CH 1 /* M62332 volume channel number */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0 : CH.1 , 1 : CH. 2 */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DAC send data */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_SLAVE_ADDR 0x4e /* Slave address */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_W_BIT 0x00 /* W bit (0 only) */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_SUB_ADDR 0x00 /* Sub address */ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_A_BIT 0x00 /* A bit (0 only) */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DAC setup and hold times (expressed in us) */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_BUS_FREE_TIME 5 /* 4.7 us */ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_START_SETUP_TIME 5 /* 4.7 us */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_STOP_SETUP_TIME 4 /* 4.0 us */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_START_HOLD_TIME 5 /* 4.7 us */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_SCL_LOW_HOLD_TIME 5 /* 4.7 us */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_SCL_HIGH_HOLD_TIME 4 /* 4.0 us */ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_DATA_SETUP_TIME 1 /* 250 ns */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_DATA_HOLD_TIME 1 /* 300 ns */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_LOW_SETUP_TIME 1 /* 300 ns */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_HIGH_SETUP_TIME 1 /* 1000 ns */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the following is the overall data for the locomo chip */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct locomo { 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long phys; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int irq; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *base; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct locomo_dev_info { 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long offset; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long length; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int devid; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int irq[1]; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char * name; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* All the locomo devices. If offset is non-zero, the mapbase for the 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locomo_dev will be set to the chip base plus offset. If offset is 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zero, then the mapbase for the locomo_dev will be set to zero. An 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * offset of zero means the device only uses GPIOs or other helper 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * functions inside this file */ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct locomo_dev_info locomo_devices[] = { 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_KEYBOARD, 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = { 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRQ_LOCOMO_KEY, 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-keyboard", 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_KEYBOARD, 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 16, 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_FRONTLIGHT, 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-frontlight", 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_FRONTLIGHT, 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 8, 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_BACKLIGHT, 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-backlight", 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_BACKLIGHT, 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 8, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_AUDIO, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-audio", 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_AUDIO, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 4, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_LED, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-led", 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_LED, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 8, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_UART, 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-uart", 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = 0, 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 0, 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** LoCoMo interrupt handling stuff. 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: LoCoMo has a 1 to many mapping on all of its IRQs. 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that is, there is only one real hardware interrupt 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we determine which interrupt it is by reading some IO memory. 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We have two levels of expansion, first in the handler for the 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hardware interrupt we generate an interrupt 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_*_BASE and those handlers generate more interrupts 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hardware irq reads LOCOMO_ICR & 0x0f00 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_KEY_BASE 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_GPIO_BASE 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_LT_BASE 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_SPI_BASE 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_KEY_BASE reads LOCOMO_KIC & 0x0001 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_KEY 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_GPIO_BASE reads LOCOMO_GIR & LOCOMO_GPD & 0xffff 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_GPIO[0-15] 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_LT_BASE reads LOCOMO_LTINT & 0x0001 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_LT 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_SPI_BASE reads LOCOMO_SPIIR & 0x000F 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_SPI_RFR 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_SPI_RFW 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_SPI_OVRN 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ_LOCOMO_SPI_TEND 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_START (IRQ_LOCOMO_KEY_BASE) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_KEY_START (IRQ_LOCOMO_KEY) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_GPIO_START (IRQ_LOCOMO_GPIO0) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_LT_START (IRQ_LOCOMO_LT) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LOCOMO_IRQ_SPI_START (IRQ_LOCOMO_SPI_RFR) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_handler(unsigned int irq, struct irqdesc *desc, 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs *regs) 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int req, i; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct irqdesc *d; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Acknowledge the parent IRQ */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->chip->ack(irq); 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check why this interrupt was generated */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req = locomo_readl(mapbase + LOCOMO_ICR) & 0x0f00; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req) { 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* generate the next interrupt(s) */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = LOCOMO_IRQ_START; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = irq_desc + irq; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i <= 3; i++, d++, irq++) { 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req & (0x0100 << i)) { 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->handle(irq, d, regs); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_ack_irq(unsigned int irq) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_mask_irq(unsigned int irq) 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_ICR); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0010 << (irq - LOCOMO_IRQ_START)); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_ICR); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_unmask_irq(unsigned int irq) 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_ICR); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= (0x0010 << (irq - LOCOMO_IRQ_START)); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_ICR); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_chip = { 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ack = locomo_ack_irq, 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mask = locomo_mask_irq, 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unmask = locomo_unmask_irq, 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_handler(unsigned int irq, struct irqdesc *desc, 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs *regs) 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct irqdesc *d; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = irq_desc + LOCOMO_IRQ_KEY_START; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->handle(LOCOMO_IRQ_KEY_START, d, regs); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_ack_irq(unsigned int irq) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START)); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_mask_irq(unsigned int irq) 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START)); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_key_unmask_irq(unsigned int irq) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START)); 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_key_chip = { 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ack = locomo_key_ack_irq, 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mask = locomo_key_mask_irq, 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unmask = locomo_key_unmask_irq, 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs *regs) 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int req, i; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct irqdesc *d; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req = locomo_readl(mapbase + LOCOMO_GIR) & 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_readl(mapbase + LOCOMO_GPD) & 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xffff; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req) { 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = LOCOMO_IRQ_GPIO_START; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = irq_desc + LOCOMO_IRQ_GPIO_START; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i <= 15; i++, irq++, d++) { 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req & (0x0001 << i)) { 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->handle(irq, d, regs); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_ack_irq(unsigned int irq) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_GWE); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_GWE); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_GIS); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_GIS); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_GWE); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_GWE); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_mask_irq(unsigned int irq) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_GIE); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_GIE); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_gpio_unmask_irq(unsigned int irq) 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_GIE); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_GIE); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_gpio_chip = { 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ack = locomo_gpio_ack_irq, 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mask = locomo_gpio_mask_irq, 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unmask = locomo_gpio_unmask_irq, 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_handler(unsigned int irq, struct irqdesc *desc, 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs *regs) 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct irqdesc *d; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = irq_desc + LOCOMO_IRQ_LT_START; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->handle(LOCOMO_IRQ_LT_START, d, regs); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_ack_irq(unsigned int irq) 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_LTINT); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START)); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_LTINT); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_mask_irq(unsigned int irq) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_LTINT); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START)); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_LTINT); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_lt_unmask_irq(unsigned int irq) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_LTINT); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START)); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_LTINT); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_lt_chip = { 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ack = locomo_lt_ack_irq, 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mask = locomo_lt_mask_irq, 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unmask = locomo_lt_unmask_irq, 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_handler(unsigned int irq, struct irqdesc *desc, 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs *regs) 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int req, i; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct irqdesc *d; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req = locomo_readl(mapbase + LOCOMO_SPIIR) & 0x000F; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req) { 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = LOCOMO_IRQ_SPI_START; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = irq_desc + irq; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i <= 3; i++, irq++, d++) { 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req & (0x0001 << i)) { 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->handle(irq, d, regs); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_ack_irq(unsigned int irq) 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_SPIWE); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_SPIWE); 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_SPIIS); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_SPIIS); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_SPIWE); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_SPIWE); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_mask_irq(unsigned int irq) 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_SPIIE); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_SPIIE); 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_spi_unmask_irq(unsigned int irq) 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = get_irq_chipdata(irq); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_SPIIE); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_SPIIE); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct irqchip locomo_spi_chip = { 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ack = locomo_spi_ack_irq, 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mask = locomo_spi_mask_irq, 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unmask = locomo_spi_unmask_irq, 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_setup_irq(struct locomo *lchip) 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int irq; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *irqbase = lchip->base; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Install handler for IRQ_LOCOMO_HW. 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_type(lchip->irq, IRQT_FALLING); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(lchip->irq, irqbase); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chained_handler(lchip->irq, locomo_handler); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Install handlers for IRQ_LOCOMO_*_BASE */ 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(IRQ_LOCOMO_KEY_BASE, irqbase); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(IRQ_LOCOMO_KEY_BASE, IRQF_VALID | IRQF_PROBE); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(IRQ_LOCOMO_GPIO_BASE, irqbase); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(IRQ_LOCOMO_GPIO_BASE, IRQF_VALID | IRQF_PROBE); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip); 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(IRQ_LOCOMO_LT_BASE, irqbase); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(IRQ_LOCOMO_LT_BASE, IRQF_VALID | IRQF_PROBE); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(IRQ_LOCOMO_SPI_BASE, irqbase); 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(IRQ_LOCOMO_SPI_BASE, IRQF_VALID | IRQF_PROBE); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */ 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(LOCOMO_IRQ_KEY_START, irqbase); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_handler(LOCOMO_IRQ_KEY_START, do_edge_IRQ); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */ 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) { 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chip(irq, &locomo_gpio_chip); 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(irq, irqbase); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_handler(irq, do_edge_IRQ); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */ 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(LOCOMO_IRQ_LT_START, irqbase); 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_handler(LOCOMO_IRQ_LT_START, do_edge_IRQ); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE); 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */ 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 3; irq++) { 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chip(irq, &locomo_spi_chip); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chipdata(irq, irqbase); 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_handler(irq, do_edge_IRQ); 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_dev_release(struct device *_dev) 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev = LOCOMO_DEV(_dev); 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslocomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = kmalloc(sizeof(struct locomo_dev), GFP_KERNEL); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) { 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(dev, 0, sizeof(struct locomo_dev)); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strncpy(dev->dev.bus_id,info->name,sizeof(dev->dev.bus_id)); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the parent device has a DMA mask associated with it, 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * propagate it down to the children. 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip->dev->dma_mask) { 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma_mask = *lchip->dev->dma_mask; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.dma_mask = &dev->dma_mask; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->devid = info->devid; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.parent = lchip->dev; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.bus = &locomo_bus_type; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.release = locomo_dev_release; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.coherent_dma_mask = lchip->dev->coherent_dma_mask; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (info->offset) 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mapbase = lchip->base + info->offset; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mapbase = 0; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->length = info->length; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(dev->irq, info->irq, sizeof(dev->irq)); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = device_register(&dev->dev); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locomo_probe - probe for a single LoCoMo chip. 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @phys_addr: physical address of device. 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Probe for a LoCoMo chip. This must be called 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before any other locomo-specific code. 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns: 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %-ENODEV device not found. 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %-EBUSY physical address already marked in-use. 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %0 successful. 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__locomo_probe(struct device *me, struct resource *mem, int irq) 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long r; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret = -ENODEV; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip = kmalloc(sizeof(struct locomo), GFP_KERNEL); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lchip) 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(lchip, 0, sizeof(struct locomo)); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&lchip->lock); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->dev = me; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_set_drvdata(lchip->dev, lchip); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->phys = mem->start; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->irq = irq; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Map the whole region. This also maps the 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registers for our children. 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->base = ioremap(mem->start, PAGE_SIZE); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lchip->base) { 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* locomo initialize */ 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_ICR); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* KEYBOARD */ 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* GPIO */ 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_GPO); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel( (LOCOMO_GPIO(2) | LOCOMO_GPIO(3) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds , lchip->base + LOCOMO_GPE); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel( (LOCOMO_GPIO(2) | LOCOMO_GPIO(3) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds , lchip->base + LOCOMO_GPD); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_GIE); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FrontLight */ 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Longtime timer */ 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_LTINT); 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SPI */ 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_SPIIE); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_ASD); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x8000; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_ASD); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(6 + 8 + 320 + 30 - 10 - 128 + 4, lchip->base + LOCOMO_HSD); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_HSD); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x8000; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_HSD); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(128 / 8, lchip->base + LOCOMO_HSC); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XON */ 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0x80, lchip->base + LOCOMO_TADC); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* CLK9MEN */ 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_TADC); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x10; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_TADC); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(100); 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* init DAC */ 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_DAC); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_DAC); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_VER); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "LoCoMo Chip: %lu%lu\n", (r >> 8), (r & 0xff)); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The interrupt controller must be initialised before any 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other device to ensure that the interrupts are available. 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip->irq != NO_IRQ) 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_setup_irq(lchip); 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < ARRAY_SIZE(locomo_devices); i++) 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_init_one_child(lchip, &locomo_devices[i]); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lchip); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 654e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic int locomo_remove_child(struct device *dev, void *data) 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 656e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek device_unregister(dev); 657e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek return 0; 658e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek} 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 660e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic void __locomo_remove(struct locomo *lchip) 661e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek{ 662e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek device_for_each_child(lchip->dev, NULL, locomo_remove_child); 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip->irq != NO_IRQ) { 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chained_handler(lchip->irq, NULL); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_data(lchip->irq, NULL); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(lchip->base); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lchip); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_probe(struct device *dev) 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct platform_device *pdev = to_platform_device(dev); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *mem; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int irq; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!mem) 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = platform_get_irq(pdev, 0); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return __locomo_probe(dev, mem, irq); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_remove(struct device *dev) 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip = dev_get_drvdata(dev); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip) { 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __locomo_remove(lchip); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_set_drvdata(dev, NULL); 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Not sure if this should be on the system bus or not yet. 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We really want some way to register a system device at 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the per-machine level, and then have this driver pick 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * up the registered devices. 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct device_driver locomo_device_driver = { 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo", 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bus = &platform_bus_type, 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = locomo_probe, 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = locomo_remove, 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get the parent device driver (us) structure 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from a child function device 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct locomo *locomo_chip_driver(struct locomo_dev *ldev) 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (struct locomo *)dev_get_drvdata(ldev->dev.parent); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir) 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip = locomo_chip_driver(ldev); 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPD); 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~bits; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPD); 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPE); 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dir) 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= bits; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~bits; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPE); 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits) 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip = locomo_chip_driver(ldev); 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ret; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = locomo_readl(lchip->base + LOCOMO_GPL); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret &= bits; 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits) 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip = locomo_chip_driver(ldev); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ret; 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = locomo_readl(lchip->base + LOCOMO_GPO); 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret &= bits; 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set) 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip = locomo_chip_driver(ldev); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPO); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set) 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= bits; 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~bits; 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPO); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_m62332_sendbit(void *mapbase, int bit) 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */ 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bit & 1) { 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SDAOEB; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_SETUP_TIME); /* 250 nsec */ 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */ 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel) 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip = locomo_chip_driver(ldev); 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char data; 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = lchip->base; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start */ 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_BUS_FREE_TIME); /* 5.0 usec */ 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */ 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_START_HOLD_TIME); /* 5.0 usec */ 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */ 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send slave address and W bit (LSB is W bit) */ 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = (M62332_SLAVE_ADDR << 1) | M62332_W_BIT; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, data >> (8 - i)); 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 1\n"); 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send Sub address (LSB is channel select) */ 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* channel = 0 : ch1 select */ 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* = 1 : ch2 select */ 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = M62332_SUB_ADDR + channel; 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, data >> (8 - i)); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 2\n"); 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send DAC data */ 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, dac_data >> (8 - i)); 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 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_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 3\n"); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop */ 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */ 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SDAOEB; 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */ 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 1000 nsec */ 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LoCoMo "Register Access Bus." 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We model this as a regular bus type, and hang devices directly 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * off this. 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_match(struct device *_dev, struct device_driver *_drv) 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev = LOCOMO_DEV(_dev); 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(_drv); 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev->devid == drv->devid; 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_suspend(struct device *dev, pm_message_t state) 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv && drv->suspend) 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->suspend(ldev, state); 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_resume(struct device *dev) 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv && drv->resume) 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->resume(ldev); 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_probe(struct device *dev) 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -ENODEV; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->probe) 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->probe(ldev); 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_remove(struct device *dev) 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->remove) 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->remove(ldev); 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type locomo_bus_type = { 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-bus", 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .match = locomo_match, 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = locomo_bus_suspend, 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = locomo_bus_resume, 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint locomo_driver_register(struct locomo_driver *driver) 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver->drv.probe = locomo_bus_probe; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver->drv.remove = locomo_bus_remove; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver->drv.bus = &locomo_bus_type; 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return driver_register(&driver->drv); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_driver_unregister(struct locomo_driver *driver) 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_unregister(&driver->drv); 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init locomo_init(void) 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = bus_register(&locomo_bus_type); 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_register(&locomo_device_driver); 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit locomo_exit(void) 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_unregister(&locomo_device_driver); 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus_unregister(&locomo_bus_type); 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(locomo_init); 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(locomo_exit); 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Sharp LoCoMo core driver"); 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_driver_register); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_driver_unregister); 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_set_dir); 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_read_level); 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_read_output); 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_gpio_write); 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(locomo_m62332_senddata); 1059