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 35ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao/* LoCoMo Interrupts */ 36ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao#define IRQ_LOCOMO_KEY (0) 37ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao#define IRQ_LOCOMO_GPIO (1) 38ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao#define IRQ_LOCOMO_LT (2) 39ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao#define IRQ_LOCOMO_SPI (3) 40ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* M62332 output channel selection */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_EVR_CH 1 /* M62332 volume channel number */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0 : CH.1 , 1 : CH. 2 */ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DAC send data */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_SLAVE_ADDR 0x4e /* Slave address */ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_W_BIT 0x00 /* W bit (0 only) */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_SUB_ADDR 0x00 /* Sub address */ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M62332_A_BIT 0x00 /* A bit (0 only) */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DAC setup and hold times (expressed in us) */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_BUS_FREE_TIME 5 /* 4.7 us */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_START_SETUP_TIME 5 /* 4.7 us */ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_STOP_SETUP_TIME 4 /* 4.0 us */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_START_HOLD_TIME 5 /* 4.7 us */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_SCL_LOW_HOLD_TIME 5 /* 4.7 us */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_SCL_HIGH_HOLD_TIME 4 /* 4.0 us */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_DATA_SETUP_TIME 1 /* 250 ns */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_DATA_HOLD_TIME 1 /* 300 ns */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_LOW_SETUP_TIME 1 /* 300 ns */ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_HIGH_SETUP_TIME 1 /* 1000 ns */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the following is the overall data for the locomo chip */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct locomo { 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long phys; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int irq; 67ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao int irq_base; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 69548153663bbf33ca7c244a6bbddd82c26a17c331Russell King void __iomem *base; 7093160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki#ifdef CONFIG_PM 7193160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki void *saved_state; 7293160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki#endif 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct locomo_dev_info { 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long offset; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long length; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int devid; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int irq[1]; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char * name; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* All the locomo devices. If offset is non-zero, the mapbase for the 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locomo_dev will be set to the chip base plus offset. If offset is 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zero, then the mapbase for the locomo_dev will be set to zero. An 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * offset of zero means the device only uses GPIOs or other helper 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * functions inside this file */ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct locomo_dev_info locomo_devices[] = { 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_KEYBOARD, 91ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao .irq = { IRQ_LOCOMO_KEY }, 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-keyboard", 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_KEYBOARD, 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 16, 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_FRONTLIGHT, 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-frontlight", 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_FRONTLIGHT, 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 8, 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_BACKLIGHT, 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-backlight", 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_BACKLIGHT, 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 8, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_AUDIO, 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-audio", 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_AUDIO, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 4, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_LED, 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-led", 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = LOCOMO_LED, 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 8, 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .devid = LOCOMO_DEVID_UART, 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq = {}, 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-uart", 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .offset = 0, 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .length = 0, 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 132a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer { 133a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer .devid = LOCOMO_DEVID_SPI, 134a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer .irq = {}, 135a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer .name = "locomo-spi", 136a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer .offset = LOCOMO_SPI, 137a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer .length = 0x30, 138a2025e7f73ae5eab0a25dad88c60aba67e3ae690Dirk Opfer }, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14110dd5ce28d78e2440e8fa1135d17e33399d75340Russell Kingstatic void locomo_handler(unsigned int irq, struct irq_desc *desc) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1436845664a6a7d443f03883db59d10749d38d98b8eThomas Gleixner struct locomo *lchip = irq_get_chip_data(irq); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int req, i; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Acknowledge the parent IRQ */ 147680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek desc->irq_data.chip->irq_ack(&desc->irq_data); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check why this interrupt was generated */ 150ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao req = locomo_readl(lchip->base + LOCOMO_ICR) & 0x0f00; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req) { 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* generate the next interrupt(s) */ 154ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao irq = lchip->irq_base; 155d8aa0251f12546e9bd1e9ee1d9782d6492819a04Dmitry Eremin-Solenikov for (i = 0; i <= 3; i++, irq++) { 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req & (0x0100 << i)) { 157d8aa0251f12546e9bd1e9ee1d9782d6492819a04Dmitry Eremin-Solenikov generic_handle_irq(irq); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 164680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhekstatic void locomo_ack_irq(struct irq_data *d) 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 168680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhekstatic void locomo_mask_irq(struct irq_data *d) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 170680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek struct locomo *lchip = irq_data_get_irq_chip_data(d); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 172ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao r = locomo_readl(lchip->base + LOCOMO_ICR); 173680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek r &= ~(0x0010 << (d->irq - lchip->irq_base)); 174ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao locomo_writel(r, lchip->base + LOCOMO_ICR); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 177680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhekstatic void locomo_unmask_irq(struct irq_data *d) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 179680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek struct locomo *lchip = irq_data_get_irq_chip_data(d); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 181ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao r = locomo_readl(lchip->base + LOCOMO_ICR); 182680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek r |= (0x0010 << (d->irq - lchip->irq_base)); 183ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao locomo_writel(r, lchip->base + LOCOMO_ICR); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18638c677cb9a683c9d477f845484b74b0a1b23e1fbDavid Brownellstatic struct irq_chip locomo_chip = { 187680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek .name = "LOCOMO", 188680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek .irq_ack = locomo_ack_irq, 189680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek .irq_mask = locomo_mask_irq, 190680244df886face4d29d3f75d964c8e45e0e8bdaLennert Buytenhek .irq_unmask = locomo_unmask_irq, 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_setup_irq(struct locomo *lchip) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 195ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao int irq = lchip->irq_base; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Install handler for IRQ_LOCOMO_HW. 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2006845664a6a7d443f03883db59d10749d38d98b8eThomas Gleixner irq_set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING); 2016845664a6a7d443f03883db59d10749d38d98b8eThomas Gleixner irq_set_chip_data(lchip->irq, lchip); 2026845664a6a7d443f03883db59d10749d38d98b8eThomas Gleixner irq_set_chained_handler(lchip->irq, locomo_handler); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 204ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao /* Install handlers for IRQ_LOCOMO_* */ 205ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao for ( ; irq <= lchip->irq_base + 3; irq++) { 206f38c02f3b338651e145aac2889ba976baf6b28b3Thomas Gleixner irq_set_chip_and_handler(irq, &locomo_chip, handle_level_irq); 2079323f26186403433293e87e717a7785f74f75d80Thomas Gleixner irq_set_chip_data(irq, lchip); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_dev_release(struct device *_dev) 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev = LOCOMO_DEV(_dev); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslocomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 226d2a02b93cf78205dd23226efb66481569900976eRussell King dev = kzalloc(sizeof(struct locomo_dev), GFP_KERNEL); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) { 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the parent device has a DMA mask associated with it, 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * propagate it down to the children. 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip->dev->dma_mask) { 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma_mask = *lchip->dev->dma_mask; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.dma_mask = &dev->dma_mask; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2413f9787046ea37a26170dc4439efa21f8d23a9978Kay Sievers dev_set_name(&dev->dev, "%s", info->name); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->devid = info->devid; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.parent = lchip->dev; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.bus = &locomo_bus_type; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.release = locomo_dev_release; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.coherent_dma_mask = lchip->dev->coherent_dma_mask; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (info->offset) 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mapbase = lchip->base + info->offset; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mapbase = 0; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->length = info->length; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 254ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao dev->irq[0] = (lchip->irq_base == NO_IRQ) ? 255ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao NO_IRQ : lchip->irq_base + info->irq[0]; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = device_register(&dev->dev); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 265b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#ifdef CONFIG_PM 266b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 267b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenzstruct locomo_save_data { 268b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_GPO; 269b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_SPICT; 270b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_GPE; 271b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_ASD; 272b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_SPIMD; 273b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz}; 274b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 2753ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_suspend(struct platform_device *dev, pm_message_t state) 276b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz{ 2773ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct locomo *lchip = platform_get_drvdata(dev); 278b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz struct locomo_save_data *save; 279b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz unsigned long flags; 280b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 281b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL); 282b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz if (!save) 283b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz return -ENOMEM; 284b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 28593160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki lchip->saved_state = save; 286b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 287b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz spin_lock_irqsave(&lchip->lock, flags); 288b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 289b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ 290b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_GPO); 2912a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT); /* SPI */ 2921b0d76cb9d5a65567230097a2512046f09f30523H Hartley Sweeten locomo_writel(0x40, lchip->base + LOCOMO_SPI + LOCOMO_SPICT); 293b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */ 294b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_GPE); 295b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */ 296b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_ASD); 2972a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); /* SPI */ 2982a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel(0x3C14, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); 299b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 300b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_PAIF); 301b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_DAC); 302b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC); 303b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 3042a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze if ((locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88)) 305b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */ 306b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz else 307b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz /* 18MHz already enabled, so no wait */ 308b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0xc1, lchip->base + LOCOMO_C32K); /* CLK32 on */ 309b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 310b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_TADC); /* 18MHz clock off*/ 311b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC); /* 22MHz/24MHz clock off */ 312b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); /* FL */ 313b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 314b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz spin_unlock_irqrestore(&lchip->lock, flags); 315b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 316b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz return 0; 317b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz} 318b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 3193ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_resume(struct platform_device *dev) 320b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz{ 3213ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct locomo *lchip = platform_get_drvdata(dev); 322b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz struct locomo_save_data *save; 323b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz unsigned long r; 324b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz unsigned long flags; 32593160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki 32693160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki save = lchip->saved_state; 327b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz if (!save) 328b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz return 0; 329b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 330b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz spin_lock_irqsave(&lchip->lock, flags); 331b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 332b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO); 3332a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPI + LOCOMO_SPICT); 334b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE); 335b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD); 3362a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); 337b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 338b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_C32K); 339b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x90, lchip->base + LOCOMO_TADC); 340b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 341b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC); 342b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); 343b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz r &= 0xFEFF; 344b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); 345b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); 346b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 347b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz spin_unlock_irqrestore(&lchip->lock, flags); 34893160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki 34993160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki lchip->saved_state = NULL; 350b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz kfree(save); 351b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 352b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz return 0; 353b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz} 354b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#endif 355b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 3564ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locomo_probe - probe for a single LoCoMo chip. 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @phys_addr: physical address of device. 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Probe for a LoCoMo chip. This must be called 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before any other locomo-specific code. 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns: 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %-ENODEV device not found. 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %-EBUSY physical address already marked in-use. 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %0 successful. 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__locomo_probe(struct device *me, struct resource *mem, int irq) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 372ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao struct locomo_platform_data *pdata = me->platform_data; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long r; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret = -ENODEV; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 377d2a02b93cf78205dd23226efb66481569900976eRussell King lchip = kzalloc(sizeof(struct locomo), GFP_KERNEL); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lchip) 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&lchip->lock); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->dev = me; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_set_drvdata(lchip->dev, lchip); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->phys = mem->start; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->irq = irq; 388ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao lchip->irq_base = (pdata) ? pdata->irq_base : NO_IRQ; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Map the whole region. This also maps the 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registers for our children. 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->base = ioremap(mem->start, PAGE_SIZE); 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lchip->base) { 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* locomo initialize */ 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_ICR); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* KEYBOARD */ 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* GPIO */ 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_GPO); 4072a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds , lchip->base + LOCOMO_GPE); 4092a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds , lchip->base + LOCOMO_GPD); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_GIE); 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 413e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie /* Frontlight */ 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); 4164ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Longtime timer */ 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_LTINT); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SPI */ 4201b0d76cb9d5a65567230097a2512046f09f30523H Hartley Sweeten locomo_writel(0, lchip->base + LOCOMO_SPI + LOCOMO_SPIIE); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_ASD); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x8000; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_ASD); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(6 + 8 + 320 + 30 - 10 - 128 + 4, lchip->base + LOCOMO_HSD); 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_HSD); 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x8000; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_HSD); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(128 / 8, lchip->base + LOCOMO_HSC); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XON */ 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0x80, lchip->base + LOCOMO_TADC); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* CLK9MEN */ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_TADC); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x10; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_TADC); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(100); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* init DAC */ 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_DAC); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_DAC); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_VER); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "LoCoMo Chip: %lu%lu\n", (r >> 8), (r & 0xff)); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The interrupt controller must be initialised before any 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other device to ensure that the interrupts are available. 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 455ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao if (lchip->irq != NO_IRQ && lchip->irq_base != NO_IRQ) 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_setup_irq(lchip); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < ARRAY_SIZE(locomo_devices); i++) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_init_one_child(lchip, &locomo_devices[i]); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lchip); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 467e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic int locomo_remove_child(struct device *dev, void *data) 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 469e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek device_unregister(dev); 470e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek return 0; 471e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek} 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 473e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic void __locomo_remove(struct locomo *lchip) 474e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek{ 475e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek device_for_each_child(lchip->dev, NULL, locomo_remove_child); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip->irq != NO_IRQ) { 4786845664a6a7d443f03883db59d10749d38d98b8eThomas Gleixner irq_set_chained_handler(lchip->irq, NULL); 4796845664a6a7d443f03883db59d10749d38d98b8eThomas Gleixner irq_set_handler_data(lchip->irq, NULL); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(lchip->base); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lchip); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4863ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_probe(struct platform_device *dev) 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *mem; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int irq; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4913ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King mem = platform_get_resource(dev, IORESOURCE_MEM, 0); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!mem) 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4943ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King irq = platform_get_irq(dev, 0); 495489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel if (irq < 0) 496489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel return -ENXIO; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4983ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King return __locomo_probe(&dev->dev, mem, irq); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5013ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_remove(struct platform_device *dev) 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 503c35bf4a593631850ab437b37ddcded4e05548e9ePavel Machek struct locomo *lchip = platform_get_drvdata(dev); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip) { 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __locomo_remove(lchip); 5073ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_set_drvdata(dev, NULL); 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Not sure if this should be on the system bus or not yet. 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We really want some way to register a system device at 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the per-machine level, and then have this driver pick 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * up the registered devices. 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5193ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver locomo_device_driver = { 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = locomo_probe, 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = locomo_remove, 522b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#ifdef CONFIG_PM 523b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz .suspend = locomo_suspend, 524b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz .resume = locomo_resume, 525b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#endif 5263ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .driver = { 5273ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .name = "locomo", 5283ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King }, 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get the parent device driver (us) structure 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from a child function device 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct locomo *locomo_chip_driver(struct locomo_dev *ldev) 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (struct locomo *)dev_get_drvdata(ldev->dev.parent); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5408d48427ecb0639593ccf14e807479b7873254ccbRichard Purdievoid locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir) 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5428d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie struct locomo *lchip = dev_get_drvdata(dev); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5468d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie if (!lchip) 5478d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie return; 5488d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPD); 5522a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze if (dir) 5532a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze r |= bits; 5542a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze else 5552a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze r &= ~bits; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPD); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPE); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dir) 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= bits; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~bits; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPE); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5679c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_gpio_set_dir); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5698d48427ecb0639593ccf14e807479b7873254ccbRichard Purdieint locomo_gpio_read_level(struct device *dev, unsigned int bits) 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5718d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie struct locomo *lchip = dev_get_drvdata(dev); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ret; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5758d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie if (!lchip) 5768d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie return -ENODEV; 5778d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = locomo_readl(lchip->base + LOCOMO_GPL); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret &= bits; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5859c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_gpio_read_level); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5878d48427ecb0639593ccf14e807479b7873254ccbRichard Purdieint locomo_gpio_read_output(struct device *dev, unsigned int bits) 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5898d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie struct locomo *lchip = dev_get_drvdata(dev); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ret; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5938d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie if (!lchip) 5948d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie return -ENODEV; 5958d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = locomo_readl(lchip->base + LOCOMO_GPO); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret &= bits; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6039c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_gpio_read_output); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6058d48427ecb0639593ccf14e807479b7873254ccbRichard Purdievoid locomo_gpio_write(struct device *dev, unsigned int bits, unsigned int set) 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6078d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie struct locomo *lchip = dev_get_drvdata(dev); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6118d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie if (!lchip) 6128d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie return; 6138d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPO); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= bits; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~bits; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPO); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6259c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_gpio_write); 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_m62332_sendbit(void *mapbase, int bit) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */ 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bit & 1) { 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SDAOEB; 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_SETUP_TIME); /* 250 nsec */ 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel) 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip = locomo_chip_driver(ldev); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char data; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = lchip->base; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start */ 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_BUS_FREE_TIME); /* 5.0 usec */ 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */ 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_START_HOLD_TIME); /* 5.0 usec */ 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */ 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send slave address and W bit (LSB is W bit) */ 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = (M62332_SLAVE_ADDR << 1) | M62332_W_BIT; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, data >> (8 - i)); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 1\n"); 709c8c3dcb9df8025ed48f8b14bf4b8a77801d88758H Hartley Sweeten goto out; 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send Sub address (LSB is channel select) */ 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* channel = 0 : ch1 select */ 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* = 1 : ch2 select */ 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = M62332_SUB_ADDR + channel; 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, data >> (8 - i)); 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 2\n"); 737c8c3dcb9df8025ed48f8b14bf4b8a77801d88758H Hartley Sweeten goto out; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send DAC data */ 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, dac_data >> (8 - i)); 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 3\n"); 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 764c8c3dcb9df8025ed48f8b14bf4b8a77801d88758H Hartley Sweetenout: 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop */ 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */ 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SDAOEB; 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */ 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 1000 nsec */ 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7909c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_m62332_senddata); 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 793e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie * Frontlight control 794e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie */ 795e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie 796e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdievoid locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf) 797e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie{ 798e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie unsigned long flags; 799e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie struct locomo *lchip = locomo_chip_driver(dev); 800e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie 801e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie if (vr) 8028d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 1); 803e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie else 8048d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 0); 805e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie 806e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie spin_lock_irqsave(&lchip->lock, flags); 807e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); 808e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie udelay(100); 809e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); 810e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); 811e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie spin_unlock_irqrestore(&lchip->lock, flags); 812e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie} 8139179825cf5e96bd0784456ef43811cab4db17cd9Eric MiaoEXPORT_SYMBOL(locomo_frontlight_set); 814e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie 815e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie/* 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LoCoMo "Register Access Bus." 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We model this as a regular bus type, and hang devices directly 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * off this. 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_match(struct device *_dev, struct device_driver *_drv) 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev = LOCOMO_DEV(_dev); 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(_drv); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev->devid == drv->devid; 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_suspend(struct device *dev, pm_message_t state) 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv && drv->suspend) 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->suspend(ldev, state); 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_resume(struct device *dev) 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv && drv->resume) 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->resume(ldev); 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_probe(struct device *dev) 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -ENODEV; 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->probe) 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->probe(ldev); 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_remove(struct device *dev) 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->remove) 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->remove(ldev); 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type locomo_bus_type = { 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-bus", 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .match = locomo_match, 876306955be37dd1b1f232f19766227ccccb83f7873Russell King .probe = locomo_bus_probe, 877306955be37dd1b1f232f19766227ccccb83f7873Russell King .remove = locomo_bus_remove, 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = locomo_bus_suspend, 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = locomo_bus_resume, 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint locomo_driver_register(struct locomo_driver *driver) 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver->drv.bus = &locomo_bus_type; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return driver_register(&driver->drv); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8879c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_driver_register); 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_driver_unregister(struct locomo_driver *driver) 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_unregister(&driver->drv); 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8939c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_driver_unregister); 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init locomo_init(void) 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = bus_register(&locomo_bus_type); 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 8993ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_driver_register(&locomo_device_driver); 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit locomo_exit(void) 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9053ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_driver_unregister(&locomo_device_driver); 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus_unregister(&locomo_bus_type); 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(locomo_init); 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(locomo_exit); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Sharp LoCoMo core driver"); 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); 915