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