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