locomo.c revision 680244df886face4d29d3f75d964c8e45e0e8bda
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{ 143ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao struct locomo *lchip = get_irq_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 */ 2006cab48602996cdbcb277375a8107d53e21e8c9b9Dmitry Eremin-Solenikov set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING); 201ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao set_irq_chip_data(lchip->irq, lchip); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chained_handler(lchip->irq, locomo_handler); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 204ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao /* Install handlers for IRQ_LOCOMO_* */ 205ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao for ( ; irq <= lchip->irq_base + 3; irq++) { 20600dd8027b913088ff9b656c5aaa6336c303b7f26Eric Miao set_irq_chip(irq, &locomo_chip); 207ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao set_irq_chip_data(irq, lchip); 208ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao set_irq_handler(irq, handle_level_irq); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_dev_release(struct device *_dev) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev = LOCOMO_DEV(_dev); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslocomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 227d2a02b93cf78205dd23226efb66481569900976eRussell King dev = kzalloc(sizeof(struct locomo_dev), GFP_KERNEL); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) { 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the parent device has a DMA mask associated with it, 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * propagate it down to the children. 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip->dev->dma_mask) { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma_mask = *lchip->dev->dma_mask; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.dma_mask = &dev->dma_mask; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2423f9787046ea37a26170dc4439efa21f8d23a9978Kay Sievers dev_set_name(&dev->dev, "%s", info->name); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->devid = info->devid; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.parent = lchip->dev; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.bus = &locomo_bus_type; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.release = locomo_dev_release; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev.coherent_dma_mask = lchip->dev->coherent_dma_mask; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (info->offset) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mapbase = lchip->base + info->offset; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mapbase = 0; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->length = info->length; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 255ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao dev->irq[0] = (lchip->irq_base == NO_IRQ) ? 256ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao NO_IRQ : lchip->irq_base + info->irq[0]; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = device_register(&dev->dev); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 266b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#ifdef CONFIG_PM 267b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 268b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenzstruct locomo_save_data { 269b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_GPO; 270b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_SPICT; 271b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_GPE; 272b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_ASD; 273b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz u16 LCM_SPIMD; 274b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz}; 275b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 2763ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_suspend(struct platform_device *dev, pm_message_t state) 277b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz{ 2783ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct locomo *lchip = platform_get_drvdata(dev); 279b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz struct locomo_save_data *save; 280b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz unsigned long flags; 281b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 282b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL); 283b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz if (!save) 284b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz return -ENOMEM; 285b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 28693160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki lchip->saved_state = save; 287b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 288b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz spin_lock_irqsave(&lchip->lock, flags); 289b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 290b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ 291b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_GPO); 2922a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT); /* SPI */ 2931b0d76cb9d5a65567230097a2512046f09f30523H Hartley Sweeten locomo_writel(0x40, lchip->base + LOCOMO_SPI + LOCOMO_SPICT); 294b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */ 295b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_GPE); 296b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */ 297b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_ASD); 2982a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); /* SPI */ 2992a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel(0x3C14, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); 300b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 301b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_PAIF); 302b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_DAC); 303b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC); 304b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 3052a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze if ((locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88)) 306b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */ 307b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz else 308b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz /* 18MHz already enabled, so no wait */ 309b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0xc1, lchip->base + LOCOMO_C32K); /* CLK32 on */ 310b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 311b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_TADC); /* 18MHz clock off*/ 312b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC); /* 22MHz/24MHz clock off */ 313b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); /* FL */ 314b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 315b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz spin_unlock_irqrestore(&lchip->lock, flags); 316b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 317b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz return 0; 318b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz} 319b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 3203ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_resume(struct platform_device *dev) 321b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz{ 3223ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct locomo *lchip = platform_get_drvdata(dev); 323b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz struct locomo_save_data *save; 324b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz unsigned long r; 325b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz unsigned long flags; 32693160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki 32793160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki save = lchip->saved_state; 328b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz if (!save) 329b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz return 0; 330b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 331b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz spin_lock_irqsave(&lchip->lock, flags); 332b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 333b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO); 3342a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPI + LOCOMO_SPICT); 335b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE); 336b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD); 3372a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); 338b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 339b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x00, lchip->base + LOCOMO_C32K); 340b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x90, lchip->base + LOCOMO_TADC); 341b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 342b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC); 343b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); 344b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz r &= 0xFEFF; 345b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); 346b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); 347b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 348b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz spin_unlock_irqrestore(&lchip->lock, flags); 34993160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki 35093160c6397e460bc4c7ac15323fb698f91ef02e5Rafael J. Wysocki lchip->saved_state = NULL; 351b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz kfree(save); 352b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 353b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz return 0; 354b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz} 355b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#endif 356b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz 3574ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * locomo_probe - probe for a single LoCoMo chip. 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @phys_addr: physical address of device. 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Probe for a LoCoMo chip. This must be called 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before any other locomo-specific code. 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns: 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %-ENODEV device not found. 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %-EBUSY physical address already marked in-use. 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %0 successful. 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__locomo_probe(struct device *me, struct resource *mem, int irq) 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 373ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao struct locomo_platform_data *pdata = me->platform_data; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long r; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret = -ENODEV; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 378d2a02b93cf78205dd23226efb66481569900976eRussell King lchip = kzalloc(sizeof(struct locomo), GFP_KERNEL); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lchip) 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&lchip->lock); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->dev = me; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_set_drvdata(lchip->dev, lchip); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->phys = mem->start; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->irq = irq; 389ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao lchip->irq_base = (pdata) ? pdata->irq_base : NO_IRQ; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Map the whole region. This also maps the 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registers for our children. 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lchip->base = ioremap(mem->start, PAGE_SIZE); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lchip->base) { 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* locomo initialize */ 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_ICR); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* KEYBOARD */ 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* GPIO */ 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_GPO); 4082a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds , lchip->base + LOCOMO_GPE); 4102a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds , lchip->base + LOCOMO_GPD); 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_GIE); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 414e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie /* Frontlight */ 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); 4174ebf2d00260bac5213c5dfb8d257e15e40503725Pavel Machek 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Longtime timer */ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0, lchip->base + LOCOMO_LTINT); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SPI */ 4211b0d76cb9d5a65567230097a2512046f09f30523H Hartley Sweeten locomo_writel(0, lchip->base + LOCOMO_SPI + LOCOMO_SPIIE); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_ASD); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x8000; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_ASD); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(6 + 8 + 320 + 30 - 10 - 128 + 4, lchip->base + LOCOMO_HSD); 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_HSD); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x8000; 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_HSD); 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(128 / 8, lchip->base + LOCOMO_HSC); 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XON */ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(0x80, lchip->base + LOCOMO_TADC); 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* CLK9MEN */ 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_TADC); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= 0x10; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_TADC); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(100); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* init DAC */ 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_DAC); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_DAC); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_VER); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "LoCoMo Chip: %lu%lu\n", (r >> 8), (r & 0xff)); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The interrupt controller must be initialised before any 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other device to ensure that the interrupts are available. 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 456ac609d266e4af4ebf586d610bd76e04dddae0c4cEric Miao if (lchip->irq != NO_IRQ && lchip->irq_base != NO_IRQ) 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_setup_irq(lchip); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < ARRAY_SIZE(locomo_devices); i++) 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_init_one_child(lchip, &locomo_devices[i]); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lchip); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 468e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic int locomo_remove_child(struct device *dev, void *data) 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 470e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek device_unregister(dev); 471e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek return 0; 472e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek} 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 474e24da5d316667a91b3a19b5761a211946ec649bbPavel Machekstatic void __locomo_remove(struct locomo *lchip) 475e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek{ 476e24da5d316667a91b3a19b5761a211946ec649bbPavel Machek device_for_each_child(lchip->dev, NULL, locomo_remove_child); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip->irq != NO_IRQ) { 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_chained_handler(lchip->irq, NULL); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_irq_data(lchip->irq, NULL); 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(lchip->base); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lchip); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4873ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_probe(struct platform_device *dev) 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *mem; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int irq; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4923ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King mem = platform_get_resource(dev, IORESOURCE_MEM, 0); 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!mem) 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4953ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King irq = platform_get_irq(dev, 0); 496489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel if (irq < 0) 497489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel return -ENXIO; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4993ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King return __locomo_probe(&dev->dev, mem, irq); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5023ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int locomo_remove(struct platform_device *dev) 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 504c35bf4a593631850ab437b37ddcded4e05548e9ePavel Machek struct locomo *lchip = platform_get_drvdata(dev); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lchip) { 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __locomo_remove(lchip); 5083ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_set_drvdata(dev, NULL); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Not sure if this should be on the system bus or not yet. 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We really want some way to register a system device at 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the per-machine level, and then have this driver pick 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * up the registered devices. 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5203ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver locomo_device_driver = { 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = locomo_probe, 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = locomo_remove, 523b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#ifdef CONFIG_PM 524b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz .suspend = locomo_suspend, 525b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz .resume = locomo_resume, 526b38d950d3aedf90c8b15b3c7c799b5eb53c47c45John Lenz#endif 5273ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .driver = { 5283ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .name = "locomo", 5293ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King }, 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get the parent device driver (us) structure 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from a child function device 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct locomo *locomo_chip_driver(struct locomo_dev *ldev) 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (struct locomo *)dev_get_drvdata(ldev->dev.parent); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5418d48427ecb0639593ccf14e807479b7873254ccbRichard Purdievoid locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir) 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5438d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie struct locomo *lchip = dev_get_drvdata(dev); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5478d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie if (!lchip) 5488d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie return; 5498d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPD); 5532a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze if (dir) 5542a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze r |= bits; 5552a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze else 5562a52efb2cecf78201d61bd4930153bf52e57503bThomas Kunze r &= ~bits; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPD); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPE); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dir) 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= bits; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~bits; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPE); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5689c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_gpio_set_dir); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5708d48427ecb0639593ccf14e807479b7873254ccbRichard Purdieint locomo_gpio_read_level(struct device *dev, unsigned int bits) 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5728d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie struct locomo *lchip = dev_get_drvdata(dev); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ret; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5768d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie if (!lchip) 5778d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie return -ENODEV; 5788d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = locomo_readl(lchip->base + LOCOMO_GPL); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret &= bits; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5869c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_gpio_read_level); 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5888d48427ecb0639593ccf14e807479b7873254ccbRichard Purdieint locomo_gpio_read_output(struct device *dev, unsigned int bits) 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5908d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie struct locomo *lchip = dev_get_drvdata(dev); 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ret; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5948d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie if (!lchip) 5958d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie return -ENODEV; 5968d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = locomo_readl(lchip->base + LOCOMO_GPO); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret &= bits; 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6049c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_gpio_read_output); 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6068d48427ecb0639593ccf14e807479b7873254ccbRichard Purdievoid locomo_gpio_write(struct device *dev, unsigned int bits, unsigned int set) 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6088d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie struct locomo *lchip = dev_get_drvdata(dev); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6128d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie if (!lchip) 6138d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie return; 6148d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(lchip->base + LOCOMO_GPO); 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (set) 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= bits; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~bits; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, lchip->base + LOCOMO_GPO); 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6269c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_gpio_write); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void locomo_m62332_sendbit(void *mapbase, int bit) 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */ 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bit & 1) { 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SDAOEB; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_SETUP_TIME); /* 250 nsec */ 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */ 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel) 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo *lchip = locomo_chip_driver(ldev); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char data; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int r; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *mapbase = lchip->base; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lchip->lock, flags); 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start */ 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_BUS_FREE_TIME); /* 5.0 usec */ 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */ 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_START_HOLD_TIME); /* 5.0 usec */ 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */ 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send slave address and W bit (LSB is W bit) */ 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = (M62332_SLAVE_ADDR << 1) | M62332_W_BIT; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, data >> (8 - i)); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 1\n"); 710c8c3dcb9df8025ed48f8b14bf4b8a77801d88758H Hartley Sweeten goto out; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send Sub address (LSB is channel select) */ 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* channel = 0 : ch1 select */ 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* = 1 : ch2 select */ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = M62332_SUB_ADDR + channel; 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, data >> (8 - i)); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 2\n"); 738c8c3dcb9df8025ed48f8b14bf4b8a77801d88758H Hartley Sweeten goto out; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Send DAC data */ 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 8; i++) { 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_m62332_sendbit(mapbase, dac_data >> (8 - i)); 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check A bit */ 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SDAOEB); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "locomo: m62332_senddata Error 3\n"); 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 765c8c3dcb9df8025ed48f8b14bf4b8a77801d88758H Hartley Sweetenout: 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop */ 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r &= ~(LOCOMO_DAC_SCLOEB); 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */ 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB; 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */ 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SDAOEB; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */ 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */ 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = locomo_readl(mapbase + LOCOMO_DAC); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds locomo_writel(r, mapbase + LOCOMO_DAC); 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_LOW_SETUP_TIME); /* 1000 nsec */ 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */ 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lchip->lock, flags); 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7919c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_m62332_senddata); 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 794e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie * Frontlight control 795e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie */ 796e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie 797e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdievoid locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf) 798e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie{ 799e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie unsigned long flags; 800e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie struct locomo *lchip = locomo_chip_driver(dev); 801e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie 802e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie if (vr) 8038d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 1); 804e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie else 8058d48427ecb0639593ccf14e807479b7873254ccbRichard Purdie locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 0); 806e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie 807e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie spin_lock_irqsave(&lchip->lock, flags); 808e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); 809e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie udelay(100); 810e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); 811e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); 812e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie spin_unlock_irqrestore(&lchip->lock, flags); 813e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie} 8149179825cf5e96bd0784456ef43811cab4db17cd9Eric MiaoEXPORT_SYMBOL(locomo_frontlight_set); 815e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie 816e4423781850025726b6c4e24ba3d93c7ff9cd826Richard Purdie/* 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LoCoMo "Register Access Bus." 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We model this as a regular bus type, and hang devices directly 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * off this. 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_match(struct device *_dev, struct device_driver *_drv) 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *dev = LOCOMO_DEV(_dev); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(_drv); 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev->devid == drv->devid; 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_suspend(struct device *dev, pm_message_t state) 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv && drv->suspend) 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->suspend(ldev, state); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_resume(struct device *dev) 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv && drv->resume) 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->resume(ldev); 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_probe(struct device *dev) 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -ENODEV; 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->probe) 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->probe(ldev); 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int locomo_bus_remove(struct device *dev) 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_dev *ldev = LOCOMO_DEV(dev); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct locomo_driver *drv = LOCOMO_DRV(dev->driver); 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->remove) 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = drv->remove(ldev); 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type locomo_bus_type = { 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "locomo-bus", 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .match = locomo_match, 877306955be37dd1b1f232f19766227ccccb83f7873Russell King .probe = locomo_bus_probe, 878306955be37dd1b1f232f19766227ccccb83f7873Russell King .remove = locomo_bus_remove, 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = locomo_bus_suspend, 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = locomo_bus_resume, 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint locomo_driver_register(struct locomo_driver *driver) 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver->drv.bus = &locomo_bus_type; 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return driver_register(&driver->drv); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8889c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_driver_register); 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid locomo_driver_unregister(struct locomo_driver *driver) 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver_unregister(&driver->drv); 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8949c5e8fecc4a86adbf363f5cf344c0ccccdbb8982Hartley SweetenEXPORT_SYMBOL(locomo_driver_unregister); 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init locomo_init(void) 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = bus_register(&locomo_bus_type); 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 9003ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_driver_register(&locomo_device_driver); 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit locomo_exit(void) 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9063ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_driver_unregister(&locomo_device_driver); 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus_unregister(&locomo_bus_type); 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(locomo_init); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(locomo_exit); 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Sharp LoCoMo core driver"); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); 916