2005-04-17 02:20:36 +04:00
/*
* linux / arch / arm / common / locomo . c
*
* Sharp LoCoMo support
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This file contains all generic LoCoMo support .
*
* All initialization functions provided here are intended to be called
* from machine specific code with proper arguments when required .
*
* Based on sa1111 . c
*/
# include <linux/config.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/delay.h>
# include <linux/errno.h>
# include <linux/ioport.h>
2005-10-29 22:07:23 +04:00
# include <linux/platform_device.h>
2005-04-17 02:20:36 +04:00
# include <linux/slab.h>
# include <linux/spinlock.h>
# include <asm/hardware.h>
# include <asm/io.h>
# include <asm/irq.h>
# include <asm/mach/irq.h>
# include <asm/hardware/locomo.h>
/* M62332 output channel selection */
# define M62332_EVR_CH 1 /* M62332 volume channel number */
/* 0 : CH.1 , 1 : CH. 2 */
/* DAC send data */
# define M62332_SLAVE_ADDR 0x4e /* Slave address */
# define M62332_W_BIT 0x00 /* W bit (0 only) */
# define M62332_SUB_ADDR 0x00 /* Sub address */
# define M62332_A_BIT 0x00 /* A bit (0 only) */
/* DAC setup and hold times (expressed in us) */
# define DAC_BUS_FREE_TIME 5 /* 4.7 us */
# define DAC_START_SETUP_TIME 5 /* 4.7 us */
# define DAC_STOP_SETUP_TIME 4 /* 4.0 us */
# define DAC_START_HOLD_TIME 5 /* 4.7 us */
# define DAC_SCL_LOW_HOLD_TIME 5 /* 4.7 us */
# define DAC_SCL_HIGH_HOLD_TIME 4 /* 4.0 us */
# define DAC_DATA_SETUP_TIME 1 /* 250 ns */
# define DAC_DATA_HOLD_TIME 1 /* 300 ns */
# define DAC_LOW_SETUP_TIME 1 /* 300 ns */
# define DAC_HIGH_SETUP_TIME 1 /* 1000 ns */
/* the following is the overall data for the locomo chip */
struct locomo {
struct device * dev ;
unsigned long phys ;
unsigned int irq ;
spinlock_t lock ;
void * base ;
} ;
struct locomo_dev_info {
unsigned long offset ;
unsigned long length ;
unsigned int devid ;
unsigned int irq [ 1 ] ;
const char * name ;
} ;
/* All the locomo devices. If offset is non-zero, the mapbase for the
* locomo_dev will be set to the chip base plus offset . If offset is
* zero , then the mapbase for the locomo_dev will be set to zero . An
* offset of zero means the device only uses GPIOs or other helper
* functions inside this file */
static struct locomo_dev_info locomo_devices [ ] = {
{
. devid = LOCOMO_DEVID_KEYBOARD ,
. irq = {
IRQ_LOCOMO_KEY ,
} ,
. name = " locomo-keyboard " ,
. offset = LOCOMO_KEYBOARD ,
. length = 16 ,
} ,
{
. devid = LOCOMO_DEVID_FRONTLIGHT ,
. irq = { } ,
. name = " locomo-frontlight " ,
. offset = LOCOMO_FRONTLIGHT ,
. length = 8 ,
} ,
{
. devid = LOCOMO_DEVID_BACKLIGHT ,
. irq = { } ,
. name = " locomo-backlight " ,
. offset = LOCOMO_BACKLIGHT ,
. length = 8 ,
} ,
{
. devid = LOCOMO_DEVID_AUDIO ,
. irq = { } ,
. name = " locomo-audio " ,
. offset = LOCOMO_AUDIO ,
. length = 4 ,
} ,
{
. devid = LOCOMO_DEVID_LED ,
. irq = { } ,
. name = " locomo-led " ,
. offset = LOCOMO_LED ,
. length = 8 ,
} ,
{
. devid = LOCOMO_DEVID_UART ,
. irq = { } ,
. name = " locomo-uart " ,
. offset = 0 ,
. length = 0 ,
} ,
} ;
/** LoCoMo interrupt handling stuff.
* NOTE : LoCoMo has a 1 to many mapping on all of its IRQs .
* that is , there is only one real hardware interrupt
* we determine which interrupt it is by reading some IO memory .
* We have two levels of expansion , first in the handler for the
* hardware interrupt we generate an interrupt
* IRQ_LOCOMO_ * _BASE and those handlers generate more interrupts
*
* hardware irq reads LOCOMO_ICR & 0x0f00
* IRQ_LOCOMO_KEY_BASE
* IRQ_LOCOMO_GPIO_BASE
* IRQ_LOCOMO_LT_BASE
* IRQ_LOCOMO_SPI_BASE
* IRQ_LOCOMO_KEY_BASE reads LOCOMO_KIC & 0x0001
* IRQ_LOCOMO_KEY
* IRQ_LOCOMO_GPIO_BASE reads LOCOMO_GIR & LOCOMO_GPD & 0xffff
* IRQ_LOCOMO_GPIO [ 0 - 15 ]
* IRQ_LOCOMO_LT_BASE reads LOCOMO_LTINT & 0x0001
* IRQ_LOCOMO_LT
* IRQ_LOCOMO_SPI_BASE reads LOCOMO_SPIIR & 0x000F
* IRQ_LOCOMO_SPI_RFR
* IRQ_LOCOMO_SPI_RFW
* IRQ_LOCOMO_SPI_OVRN
* IRQ_LOCOMO_SPI_TEND
*/
# define LOCOMO_IRQ_START (IRQ_LOCOMO_KEY_BASE)
# define LOCOMO_IRQ_KEY_START (IRQ_LOCOMO_KEY)
# define LOCOMO_IRQ_GPIO_START (IRQ_LOCOMO_GPIO0)
# define LOCOMO_IRQ_LT_START (IRQ_LOCOMO_LT)
# define LOCOMO_IRQ_SPI_START (IRQ_LOCOMO_SPI_RFR)
static void locomo_handler ( unsigned int irq , struct irqdesc * desc ,
struct pt_regs * regs )
{
int req , i ;
struct irqdesc * d ;
void * mapbase = get_irq_chipdata ( irq ) ;
/* Acknowledge the parent IRQ */
desc - > chip - > ack ( irq ) ;
/* check why this interrupt was generated */
req = locomo_readl ( mapbase + LOCOMO_ICR ) & 0x0f00 ;
if ( req ) {
/* generate the next interrupt(s) */
irq = LOCOMO_IRQ_START ;
d = irq_desc + irq ;
for ( i = 0 ; i < = 3 ; i + + , d + + , irq + + ) {
if ( req & ( 0x0100 < < i ) ) {
2005-09-04 22:45:00 +04:00
desc_handle_irq ( irq , d , regs ) ;
2005-04-17 02:20:36 +04:00
}
}
}
}
static void locomo_ack_irq ( unsigned int irq )
{
}
static void locomo_mask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_ICR ) ;
r & = ~ ( 0x0010 < < ( irq - LOCOMO_IRQ_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_ICR ) ;
}
static void locomo_unmask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_ICR ) ;
r | = ( 0x0010 < < ( irq - LOCOMO_IRQ_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_ICR ) ;
}
static struct irqchip locomo_chip = {
. ack = locomo_ack_irq ,
. mask = locomo_mask_irq ,
. unmask = locomo_unmask_irq ,
} ;
static void locomo_key_handler ( unsigned int irq , struct irqdesc * desc ,
struct pt_regs * regs )
{
struct irqdesc * d ;
void * mapbase = get_irq_chipdata ( irq ) ;
if ( locomo_readl ( mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC ) & 0x0001 ) {
d = irq_desc + LOCOMO_IRQ_KEY_START ;
2005-09-04 22:45:00 +04:00
desc_handle_irq ( LOCOMO_IRQ_KEY_START , d , regs ) ;
2005-04-17 02:20:36 +04:00
}
}
static void locomo_key_ack_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
r & = ~ ( 0x0100 < < ( irq - LOCOMO_IRQ_KEY_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
}
static void locomo_key_mask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
r & = ~ ( 0x0010 < < ( irq - LOCOMO_IRQ_KEY_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
}
static void locomo_key_unmask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
r | = ( 0x0010 < < ( irq - LOCOMO_IRQ_KEY_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
}
static struct irqchip locomo_key_chip = {
. ack = locomo_key_ack_irq ,
. mask = locomo_key_mask_irq ,
. unmask = locomo_key_unmask_irq ,
} ;
static void locomo_gpio_handler ( unsigned int irq , struct irqdesc * desc ,
struct pt_regs * regs )
{
int req , i ;
struct irqdesc * d ;
void * mapbase = get_irq_chipdata ( irq ) ;
req = locomo_readl ( mapbase + LOCOMO_GIR ) &
locomo_readl ( mapbase + LOCOMO_GPD ) &
0xffff ;
if ( req ) {
irq = LOCOMO_IRQ_GPIO_START ;
d = irq_desc + LOCOMO_IRQ_GPIO_START ;
for ( i = 0 ; i < = 15 ; i + + , irq + + , d + + ) {
if ( req & ( 0x0001 < < i ) ) {
2005-09-04 22:45:00 +04:00
desc_handle_irq ( irq , d , regs ) ;
2005-04-17 02:20:36 +04:00
}
}
}
}
static void locomo_gpio_ack_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_GWE ) ;
r | = ( 0x0001 < < ( irq - LOCOMO_IRQ_GPIO_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_GWE ) ;
r = locomo_readl ( mapbase + LOCOMO_GIS ) ;
r & = ~ ( 0x0001 < < ( irq - LOCOMO_IRQ_GPIO_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_GIS ) ;
r = locomo_readl ( mapbase + LOCOMO_GWE ) ;
r & = ~ ( 0x0001 < < ( irq - LOCOMO_IRQ_GPIO_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_GWE ) ;
}
static void locomo_gpio_mask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_GIE ) ;
r & = ~ ( 0x0001 < < ( irq - LOCOMO_IRQ_GPIO_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_GIE ) ;
}
static void locomo_gpio_unmask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_GIE ) ;
r | = ( 0x0001 < < ( irq - LOCOMO_IRQ_GPIO_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_GIE ) ;
}
static struct irqchip locomo_gpio_chip = {
. ack = locomo_gpio_ack_irq ,
. mask = locomo_gpio_mask_irq ,
. unmask = locomo_gpio_unmask_irq ,
} ;
static void locomo_lt_handler ( unsigned int irq , struct irqdesc * desc ,
struct pt_regs * regs )
{
struct irqdesc * d ;
void * mapbase = get_irq_chipdata ( irq ) ;
if ( locomo_readl ( mapbase + LOCOMO_LTINT ) & 0x0001 ) {
d = irq_desc + LOCOMO_IRQ_LT_START ;
2005-09-04 22:45:00 +04:00
desc_handle_irq ( LOCOMO_IRQ_LT_START , d , regs ) ;
2005-04-17 02:20:36 +04:00
}
}
static void locomo_lt_ack_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_LTINT ) ;
r & = ~ ( 0x0100 < < ( irq - LOCOMO_IRQ_LT_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_LTINT ) ;
}
static void locomo_lt_mask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_LTINT ) ;
r & = ~ ( 0x0010 < < ( irq - LOCOMO_IRQ_LT_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_LTINT ) ;
}
static void locomo_lt_unmask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_LTINT ) ;
r | = ( 0x0010 < < ( irq - LOCOMO_IRQ_LT_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_LTINT ) ;
}
static struct irqchip locomo_lt_chip = {
. ack = locomo_lt_ack_irq ,
. mask = locomo_lt_mask_irq ,
. unmask = locomo_lt_unmask_irq ,
} ;
static void locomo_spi_handler ( unsigned int irq , struct irqdesc * desc ,
struct pt_regs * regs )
{
int req , i ;
struct irqdesc * d ;
void * mapbase = get_irq_chipdata ( irq ) ;
req = locomo_readl ( mapbase + LOCOMO_SPIIR ) & 0x000F ;
if ( req ) {
irq = LOCOMO_IRQ_SPI_START ;
d = irq_desc + irq ;
for ( i = 0 ; i < = 3 ; i + + , irq + + , d + + ) {
if ( req & ( 0x0001 < < i ) ) {
2005-09-04 22:45:00 +04:00
desc_handle_irq ( irq , d , regs ) ;
2005-04-17 02:20:36 +04:00
}
}
}
}
static void locomo_spi_ack_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_SPIWE ) ;
r | = ( 0x0001 < < ( irq - LOCOMO_IRQ_SPI_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_SPIWE ) ;
r = locomo_readl ( mapbase + LOCOMO_SPIIS ) ;
r & = ~ ( 0x0001 < < ( irq - LOCOMO_IRQ_SPI_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_SPIIS ) ;
r = locomo_readl ( mapbase + LOCOMO_SPIWE ) ;
r & = ~ ( 0x0001 < < ( irq - LOCOMO_IRQ_SPI_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_SPIWE ) ;
}
static void locomo_spi_mask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_SPIIE ) ;
r & = ~ ( 0x0001 < < ( irq - LOCOMO_IRQ_SPI_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_SPIIE ) ;
}
static void locomo_spi_unmask_irq ( unsigned int irq )
{
void * mapbase = get_irq_chipdata ( irq ) ;
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_SPIIE ) ;
r | = ( 0x0001 < < ( irq - LOCOMO_IRQ_SPI_START ) ) ;
locomo_writel ( r , mapbase + LOCOMO_SPIIE ) ;
}
static struct irqchip locomo_spi_chip = {
. ack = locomo_spi_ack_irq ,
. mask = locomo_spi_mask_irq ,
. unmask = locomo_spi_unmask_irq ,
} ;
static void locomo_setup_irq ( struct locomo * lchip )
{
int irq ;
void * irqbase = lchip - > base ;
/*
* Install handler for IRQ_LOCOMO_HW .
*/
set_irq_type ( lchip - > irq , IRQT_FALLING ) ;
set_irq_chipdata ( lchip - > irq , irqbase ) ;
set_irq_chained_handler ( lchip - > irq , locomo_handler ) ;
/* Install handlers for IRQ_LOCOMO_*_BASE */
set_irq_chip ( IRQ_LOCOMO_KEY_BASE , & locomo_chip ) ;
set_irq_chipdata ( IRQ_LOCOMO_KEY_BASE , irqbase ) ;
set_irq_chained_handler ( IRQ_LOCOMO_KEY_BASE , locomo_key_handler ) ;
set_irq_flags ( IRQ_LOCOMO_KEY_BASE , IRQF_VALID | IRQF_PROBE ) ;
set_irq_chip ( IRQ_LOCOMO_GPIO_BASE , & locomo_chip ) ;
set_irq_chipdata ( IRQ_LOCOMO_GPIO_BASE , irqbase ) ;
set_irq_chained_handler ( IRQ_LOCOMO_GPIO_BASE , locomo_gpio_handler ) ;
set_irq_flags ( IRQ_LOCOMO_GPIO_BASE , IRQF_VALID | IRQF_PROBE ) ;
set_irq_chip ( IRQ_LOCOMO_LT_BASE , & locomo_chip ) ;
set_irq_chipdata ( IRQ_LOCOMO_LT_BASE , irqbase ) ;
set_irq_chained_handler ( IRQ_LOCOMO_LT_BASE , locomo_lt_handler ) ;
set_irq_flags ( IRQ_LOCOMO_LT_BASE , IRQF_VALID | IRQF_PROBE ) ;
set_irq_chip ( IRQ_LOCOMO_SPI_BASE , & locomo_chip ) ;
set_irq_chipdata ( IRQ_LOCOMO_SPI_BASE , irqbase ) ;
set_irq_chained_handler ( IRQ_LOCOMO_SPI_BASE , locomo_spi_handler ) ;
set_irq_flags ( IRQ_LOCOMO_SPI_BASE , IRQF_VALID | IRQF_PROBE ) ;
/* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */
set_irq_chip ( LOCOMO_IRQ_KEY_START , & locomo_key_chip ) ;
set_irq_chipdata ( LOCOMO_IRQ_KEY_START , irqbase ) ;
set_irq_handler ( LOCOMO_IRQ_KEY_START , do_edge_IRQ ) ;
set_irq_flags ( LOCOMO_IRQ_KEY_START , IRQF_VALID | IRQF_PROBE ) ;
/* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */
for ( irq = LOCOMO_IRQ_GPIO_START ; irq < LOCOMO_IRQ_GPIO_START + 16 ; irq + + ) {
set_irq_chip ( irq , & locomo_gpio_chip ) ;
set_irq_chipdata ( irq , irqbase ) ;
set_irq_handler ( irq , do_edge_IRQ ) ;
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
}
/* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */
set_irq_chip ( LOCOMO_IRQ_LT_START , & locomo_lt_chip ) ;
set_irq_chipdata ( LOCOMO_IRQ_LT_START , irqbase ) ;
set_irq_handler ( LOCOMO_IRQ_LT_START , do_edge_IRQ ) ;
set_irq_flags ( LOCOMO_IRQ_LT_START , IRQF_VALID | IRQF_PROBE ) ;
/* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */
for ( irq = LOCOMO_IRQ_SPI_START ; irq < LOCOMO_IRQ_SPI_START + 3 ; irq + + ) {
set_irq_chip ( irq , & locomo_spi_chip ) ;
set_irq_chipdata ( irq , irqbase ) ;
set_irq_handler ( irq , do_edge_IRQ ) ;
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
}
}
static void locomo_dev_release ( struct device * _dev )
{
struct locomo_dev * dev = LOCOMO_DEV ( _dev ) ;
kfree ( dev ) ;
}
static int
locomo_init_one_child ( struct locomo * lchip , struct locomo_dev_info * info )
{
struct locomo_dev * dev ;
int ret ;
dev = kmalloc ( sizeof ( struct locomo_dev ) , GFP_KERNEL ) ;
if ( ! dev ) {
ret = - ENOMEM ;
goto out ;
}
memset ( dev , 0 , sizeof ( struct locomo_dev ) ) ;
strncpy ( dev - > dev . bus_id , info - > name , sizeof ( dev - > dev . bus_id ) ) ;
/*
* If the parent device has a DMA mask associated with it ,
* propagate it down to the children .
*/
if ( lchip - > dev - > dma_mask ) {
dev - > dma_mask = * lchip - > dev - > dma_mask ;
dev - > dev . dma_mask = & dev - > dma_mask ;
}
dev - > devid = info - > devid ;
dev - > dev . parent = lchip - > dev ;
dev - > dev . bus = & locomo_bus_type ;
dev - > dev . release = locomo_dev_release ;
dev - > dev . coherent_dma_mask = lchip - > dev - > coherent_dma_mask ;
if ( info - > offset )
dev - > mapbase = lchip - > base + info - > offset ;
else
dev - > mapbase = 0 ;
dev - > length = info - > length ;
memmove ( dev - > irq , info - > irq , sizeof ( dev - > irq ) ) ;
ret = device_register ( & dev - > dev ) ;
if ( ret ) {
out :
kfree ( dev ) ;
}
return ret ;
}
2005-09-08 17:41:54 +04:00
# ifdef CONFIG_PM
struct locomo_save_data {
u16 LCM_GPO ;
u16 LCM_SPICT ;
u16 LCM_GPE ;
u16 LCM_ASD ;
u16 LCM_SPIMD ;
} ;
2005-11-10 01:32:44 +03:00
static int locomo_suspend ( struct platform_device * dev , pm_message_t state )
2005-09-08 17:41:54 +04:00
{
2005-11-10 01:32:44 +03:00
struct locomo * lchip = platform_get_drvdata ( dev ) ;
2005-09-08 17:41:54 +04:00
struct locomo_save_data * save ;
unsigned long flags ;
save = kmalloc ( sizeof ( struct locomo_save_data ) , GFP_KERNEL ) ;
if ( ! save )
return - ENOMEM ;
2005-11-10 01:32:44 +03:00
dev - > dev . power . saved_state = ( void * ) save ;
2005-09-08 17:41:54 +04:00
spin_lock_irqsave ( & lchip - > lock , flags ) ;
save - > LCM_GPO = locomo_readl ( lchip - > base + LOCOMO_GPO ) ; /* GPIO */
locomo_writel ( 0x00 , lchip - > base + LOCOMO_GPO ) ;
save - > LCM_SPICT = locomo_readl ( lchip - > base + LOCOMO_SPICT ) ; /* SPI */
locomo_writel ( 0x40 , lchip - > base + LOCOMO_SPICT ) ;
save - > LCM_GPE = locomo_readl ( lchip - > base + LOCOMO_GPE ) ; /* GPIO */
locomo_writel ( 0x00 , lchip - > base + LOCOMO_GPE ) ;
save - > LCM_ASD = locomo_readl ( lchip - > base + LOCOMO_ASD ) ; /* ADSTART */
locomo_writel ( 0x00 , lchip - > base + LOCOMO_ASD ) ;
save - > LCM_SPIMD = locomo_readl ( lchip - > base + LOCOMO_SPIMD ) ; /* SPI */
locomo_writel ( 0x3C14 , lchip - > base + LOCOMO_SPIMD ) ;
locomo_writel ( 0x00 , lchip - > base + LOCOMO_PAIF ) ;
locomo_writel ( 0x00 , lchip - > base + LOCOMO_DAC ) ;
locomo_writel ( 0x00 , lchip - > base + LOCOMO_BACKLIGHT + LOCOMO_TC ) ;
if ( ( locomo_readl ( lchip - > base + LOCOMO_LED + LOCOMO_LPT0 ) & 0x88 ) & & ( locomo_readl ( lchip - > base + LOCOMO_LED + LOCOMO_LPT1 ) & 0x88 ) )
locomo_writel ( 0x00 , lchip - > base + LOCOMO_C32K ) ; /* CLK32 off */
else
/* 18MHz already enabled, so no wait */
locomo_writel ( 0xc1 , lchip - > base + LOCOMO_C32K ) ; /* CLK32 on */
locomo_writel ( 0x00 , lchip - > base + LOCOMO_TADC ) ; /* 18MHz clock off*/
locomo_writel ( 0x00 , lchip - > base + LOCOMO_AUDIO + LOCOMO_ACC ) ; /* 22MHz/24MHz clock off */
locomo_writel ( 0x00 , lchip - > base + LOCOMO_FRONTLIGHT + LOCOMO_ALS ) ; /* FL */
spin_unlock_irqrestore ( & lchip - > lock , flags ) ;
return 0 ;
}
2005-11-10 01:32:44 +03:00
static int locomo_resume ( struct platform_device * dev )
2005-09-08 17:41:54 +04:00
{
2005-11-10 01:32:44 +03:00
struct locomo * lchip = platform_get_drvdata ( dev ) ;
2005-09-08 17:41:54 +04:00
struct locomo_save_data * save ;
unsigned long r ;
unsigned long flags ;
2005-11-10 01:32:44 +03:00
save = ( struct locomo_save_data * ) dev - > dev . power . saved_state ;
2005-09-08 17:41:54 +04:00
if ( ! save )
return 0 ;
spin_lock_irqsave ( & lchip - > lock , flags ) ;
locomo_writel ( save - > LCM_GPO , lchip - > base + LOCOMO_GPO ) ;
locomo_writel ( save - > LCM_SPICT , lchip - > base + LOCOMO_SPICT ) ;
locomo_writel ( save - > LCM_GPE , lchip - > base + LOCOMO_GPE ) ;
locomo_writel ( save - > LCM_ASD , lchip - > base + LOCOMO_ASD ) ;
locomo_writel ( save - > LCM_SPIMD , lchip - > base + LOCOMO_SPIMD ) ;
locomo_writel ( 0x00 , lchip - > base + LOCOMO_C32K ) ;
locomo_writel ( 0x90 , lchip - > base + LOCOMO_TADC ) ;
locomo_writel ( 0 , lchip - > base + LOCOMO_KEYBOARD + LOCOMO_KSC ) ;
r = locomo_readl ( lchip - > base + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
r & = 0xFEFF ;
locomo_writel ( r , lchip - > base + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
locomo_writel ( 0x1 , lchip - > base + LOCOMO_KEYBOARD + LOCOMO_KCMD ) ;
spin_unlock_irqrestore ( & lchip - > lock , flags ) ;
kfree ( save ) ;
return 0 ;
}
# endif
2006-03-15 19:03:03 +03:00
# define LCM_ALC_EN 0x8000
void frontlight_set ( struct locomo * lchip , int duty , int vr , int bpwf )
{
unsigned long flags ;
spin_lock_irqsave ( & lchip - > lock , flags ) ;
locomo_writel ( bpwf , lchip - > base + LOCOMO_FRONTLIGHT + LOCOMO_ALS ) ;
udelay ( 100 ) ;
locomo_writel ( duty , lchip - > base + LOCOMO_FRONTLIGHT + LOCOMO_ALD ) ;
locomo_writel ( bpwf | LCM_ALC_EN , lchip - > base + LOCOMO_FRONTLIGHT + LOCOMO_ALS ) ;
spin_unlock_irqrestore ( & lchip - > lock , flags ) ;
}
2005-04-17 02:20:36 +04:00
/**
* locomo_probe - probe for a single LoCoMo chip .
* @ phys_addr : physical address of device .
*
* Probe for a LoCoMo chip . This must be called
* before any other locomo - specific code .
*
* Returns :
* % - ENODEV device not found .
* % - EBUSY physical address already marked in - use .
* % 0 successful .
*/
static int
__locomo_probe ( struct device * me , struct resource * mem , int irq )
{
struct locomo * lchip ;
unsigned long r ;
int i , ret = - ENODEV ;
lchip = kmalloc ( sizeof ( struct locomo ) , GFP_KERNEL ) ;
if ( ! lchip )
return - ENOMEM ;
memset ( lchip , 0 , sizeof ( struct locomo ) ) ;
spin_lock_init ( & lchip - > lock ) ;
lchip - > dev = me ;
dev_set_drvdata ( lchip - > dev , lchip ) ;
lchip - > phys = mem - > start ;
lchip - > irq = irq ;
/*
* Map the whole region . This also maps the
* registers for our children .
*/
lchip - > base = ioremap ( mem - > start , PAGE_SIZE ) ;
if ( ! lchip - > base ) {
ret = - ENOMEM ;
goto out ;
}
/* locomo initialize */
locomo_writel ( 0 , lchip - > base + LOCOMO_ICR ) ;
/* KEYBOARD */
locomo_writel ( 0 , lchip - > base + LOCOMO_KEYBOARD + LOCOMO_KIC ) ;
/* GPIO */
locomo_writel ( 0 , lchip - > base + LOCOMO_GPO ) ;
locomo_writel ( ( LOCOMO_GPIO ( 2 ) | LOCOMO_GPIO ( 3 ) | LOCOMO_GPIO ( 13 ) | LOCOMO_GPIO ( 14 ) )
, lchip - > base + LOCOMO_GPE ) ;
locomo_writel ( ( LOCOMO_GPIO ( 2 ) | LOCOMO_GPIO ( 3 ) | LOCOMO_GPIO ( 13 ) | LOCOMO_GPIO ( 14 ) )
, lchip - > base + LOCOMO_GPD ) ;
locomo_writel ( 0 , lchip - > base + LOCOMO_GIE ) ;
/* FrontLight */
locomo_writel ( 0 , lchip - > base + LOCOMO_FRONTLIGHT + LOCOMO_ALS ) ;
locomo_writel ( 0 , lchip - > base + LOCOMO_FRONTLIGHT + LOCOMO_ALD ) ;
2006-03-15 19:03:03 +03:00
/* Same constants can be used for collie and poodle
( depending on CONFIG options in original sharp code ) ? */
frontlight_set ( lchip , 163 , 0 , 148 ) ;
2005-04-17 02:20:36 +04:00
/* Longtime timer */
locomo_writel ( 0 , lchip - > base + LOCOMO_LTINT ) ;
/* SPI */
locomo_writel ( 0 , lchip - > base + LOCOMO_SPIIE ) ;
locomo_writel ( 6 + 8 + 320 + 30 - 10 , lchip - > base + LOCOMO_ASD ) ;
r = locomo_readl ( lchip - > base + LOCOMO_ASD ) ;
r | = 0x8000 ;
locomo_writel ( r , lchip - > base + LOCOMO_ASD ) ;
locomo_writel ( 6 + 8 + 320 + 30 - 10 - 128 + 4 , lchip - > base + LOCOMO_HSD ) ;
r = locomo_readl ( lchip - > base + LOCOMO_HSD ) ;
r | = 0x8000 ;
locomo_writel ( r , lchip - > base + LOCOMO_HSD ) ;
locomo_writel ( 128 / 8 , lchip - > base + LOCOMO_HSC ) ;
/* XON */
locomo_writel ( 0x80 , lchip - > base + LOCOMO_TADC ) ;
udelay ( 1000 ) ;
/* CLK9MEN */
r = locomo_readl ( lchip - > base + LOCOMO_TADC ) ;
r | = 0x10 ;
locomo_writel ( r , lchip - > base + LOCOMO_TADC ) ;
udelay ( 100 ) ;
/* init DAC */
r = locomo_readl ( lchip - > base + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB ;
locomo_writel ( r , lchip - > base + LOCOMO_DAC ) ;
r = locomo_readl ( lchip - > base + LOCOMO_VER ) ;
printk ( KERN_INFO " LoCoMo Chip: %lu%lu \n " , ( r > > 8 ) , ( r & 0xff ) ) ;
/*
* The interrupt controller must be initialised before any
* other device to ensure that the interrupts are available .
*/
if ( lchip - > irq ! = NO_IRQ )
locomo_setup_irq ( lchip ) ;
for ( i = 0 ; i < ARRAY_SIZE ( locomo_devices ) ; i + + )
locomo_init_one_child ( lchip , & locomo_devices [ i ] ) ;
return 0 ;
out :
kfree ( lchip ) ;
return ret ;
}
2005-09-04 14:33:12 +04:00
static int locomo_remove_child ( struct device * dev , void * data )
2005-04-17 02:20:36 +04:00
{
2005-09-04 14:33:12 +04:00
device_unregister ( dev ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2005-09-04 14:33:12 +04:00
static void __locomo_remove ( struct locomo * lchip )
{
device_for_each_child ( lchip - > dev , NULL , locomo_remove_child ) ;
2005-04-17 02:20:36 +04:00
if ( lchip - > irq ! = NO_IRQ ) {
set_irq_chained_handler ( lchip - > irq , NULL ) ;
set_irq_data ( lchip - > irq , NULL ) ;
}
iounmap ( lchip - > base ) ;
kfree ( lchip ) ;
}
2005-11-10 01:32:44 +03:00
static int locomo_probe ( struct platform_device * dev )
2005-04-17 02:20:36 +04:00
{
struct resource * mem ;
int irq ;
2005-11-10 01:32:44 +03:00
mem = platform_get_resource ( dev , IORESOURCE_MEM , 0 ) ;
2005-04-17 02:20:36 +04:00
if ( ! mem )
return - EINVAL ;
2005-11-10 01:32:44 +03:00
irq = platform_get_irq ( dev , 0 ) ;
2006-01-19 20:56:29 +03:00
if ( irq < 0 )
return - ENXIO ;
2005-04-17 02:20:36 +04:00
2005-11-10 01:32:44 +03:00
return __locomo_probe ( & dev - > dev , mem , irq ) ;
2005-04-17 02:20:36 +04:00
}
2005-11-10 01:32:44 +03:00
static int locomo_remove ( struct platform_device * dev )
2005-04-17 02:20:36 +04:00
{
2005-11-12 23:25:25 +03:00
struct locomo * lchip = platform_get_drvdata ( dev ) ;
2005-04-17 02:20:36 +04:00
if ( lchip ) {
__locomo_remove ( lchip ) ;
2005-11-10 01:32:44 +03:00
platform_set_drvdata ( dev , NULL ) ;
2005-04-17 02:20:36 +04:00
}
return 0 ;
}
/*
* Not sure if this should be on the system bus or not yet .
* We really want some way to register a system device at
* the per - machine level , and then have this driver pick
* up the registered devices .
*/
2005-11-10 01:32:44 +03:00
static struct platform_driver locomo_device_driver = {
2005-04-17 02:20:36 +04:00
. probe = locomo_probe ,
. remove = locomo_remove ,
2005-09-08 17:41:54 +04:00
# ifdef CONFIG_PM
. suspend = locomo_suspend ,
. resume = locomo_resume ,
# endif
2005-11-10 01:32:44 +03:00
. driver = {
. name = " locomo " ,
} ,
2005-04-17 02:20:36 +04:00
} ;
/*
* Get the parent device driver ( us ) structure
* from a child function device
*/
static inline struct locomo * locomo_chip_driver ( struct locomo_dev * ldev )
{
return ( struct locomo * ) dev_get_drvdata ( ldev - > dev . parent ) ;
}
void locomo_gpio_set_dir ( struct locomo_dev * ldev , unsigned int bits , unsigned int dir )
{
struct locomo * lchip = locomo_chip_driver ( ldev ) ;
unsigned long flags ;
unsigned int r ;
spin_lock_irqsave ( & lchip - > lock , flags ) ;
r = locomo_readl ( lchip - > base + LOCOMO_GPD ) ;
r & = ~ bits ;
locomo_writel ( r , lchip - > base + LOCOMO_GPD ) ;
r = locomo_readl ( lchip - > base + LOCOMO_GPE ) ;
if ( dir )
r | = bits ;
else
r & = ~ bits ;
locomo_writel ( r , lchip - > base + LOCOMO_GPE ) ;
spin_unlock_irqrestore ( & lchip - > lock , flags ) ;
}
unsigned int locomo_gpio_read_level ( struct locomo_dev * ldev , unsigned int bits )
{
struct locomo * lchip = locomo_chip_driver ( ldev ) ;
unsigned long flags ;
unsigned int ret ;
spin_lock_irqsave ( & lchip - > lock , flags ) ;
ret = locomo_readl ( lchip - > base + LOCOMO_GPL ) ;
spin_unlock_irqrestore ( & lchip - > lock , flags ) ;
ret & = bits ;
return ret ;
}
unsigned int locomo_gpio_read_output ( struct locomo_dev * ldev , unsigned int bits )
{
struct locomo * lchip = locomo_chip_driver ( ldev ) ;
unsigned long flags ;
unsigned int ret ;
spin_lock_irqsave ( & lchip - > lock , flags ) ;
ret = locomo_readl ( lchip - > base + LOCOMO_GPO ) ;
spin_unlock_irqrestore ( & lchip - > lock , flags ) ;
ret & = bits ;
return ret ;
}
void locomo_gpio_write ( struct locomo_dev * ldev , unsigned int bits , unsigned int set )
{
struct locomo * lchip = locomo_chip_driver ( ldev ) ;
unsigned long flags ;
unsigned int r ;
spin_lock_irqsave ( & lchip - > lock , flags ) ;
r = locomo_readl ( lchip - > base + LOCOMO_GPO ) ;
if ( set )
r | = bits ;
else
r & = ~ bits ;
locomo_writel ( r , lchip - > base + LOCOMO_GPO ) ;
spin_unlock_irqrestore ( & lchip - > lock , flags ) ;
}
static void locomo_m62332_sendbit ( void * mapbase , int bit )
{
unsigned int r ;
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SCLOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
udelay ( DAC_DATA_HOLD_TIME ) ; /* 300 nsec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SCLOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
udelay ( DAC_SCL_LOW_HOLD_TIME ) ; /* 4.7 usec */
if ( bit & 1 ) {
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SDAOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_HIGH_SETUP_TIME ) ; /* 1000 nsec */
} else {
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SDAOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
}
udelay ( DAC_DATA_SETUP_TIME ) ; /* 250 nsec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SCLOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_HIGH_SETUP_TIME ) ; /* 1000 nsec */
udelay ( DAC_SCL_HIGH_HOLD_TIME ) ; /* 4.0 usec */
}
void locomo_m62332_senddata ( struct locomo_dev * ldev , unsigned int dac_data , int channel )
{
struct locomo * lchip = locomo_chip_driver ( ldev ) ;
int i ;
unsigned char data ;
unsigned int r ;
void * mapbase = lchip - > base ;
unsigned long flags ;
spin_lock_irqsave ( & lchip - > lock , flags ) ;
/* Start */
udelay ( DAC_BUS_FREE_TIME ) ; /* 5.0 usec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_HIGH_SETUP_TIME ) ; /* 1000 nsec */
udelay ( DAC_SCL_HIGH_HOLD_TIME ) ; /* 4.0 usec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SDAOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_START_HOLD_TIME ) ; /* 5.0 usec */
udelay ( DAC_DATA_HOLD_TIME ) ; /* 300 nsec */
/* Send slave address and W bit (LSB is W bit) */
data = ( M62332_SLAVE_ADDR < < 1 ) | M62332_W_BIT ;
for ( i = 1 ; i < = 8 ; i + + ) {
locomo_m62332_sendbit ( mapbase , data > > ( 8 - i ) ) ;
}
/* Check A bit */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SCLOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
udelay ( DAC_SCL_LOW_HOLD_TIME ) ; /* 4.7 usec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SDAOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SCLOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_HIGH_SETUP_TIME ) ; /* 1000 nsec */
udelay ( DAC_SCL_HIGH_HOLD_TIME ) ; /* 4.7 usec */
if ( locomo_readl ( mapbase + LOCOMO_DAC ) & LOCOMO_DAC_SDAOEB ) { /* High is error */
printk ( KERN_WARNING " locomo: m62332_senddata Error 1 \n " ) ;
return ;
}
/* Send Sub address (LSB is channel select) */
/* channel = 0 : ch1 select */
/* = 1 : ch2 select */
data = M62332_SUB_ADDR + channel ;
for ( i = 1 ; i < = 8 ; i + + ) {
locomo_m62332_sendbit ( mapbase , data > > ( 8 - i ) ) ;
}
/* Check A bit */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SCLOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
udelay ( DAC_SCL_LOW_HOLD_TIME ) ; /* 4.7 usec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SDAOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SCLOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_HIGH_SETUP_TIME ) ; /* 1000 nsec */
udelay ( DAC_SCL_HIGH_HOLD_TIME ) ; /* 4.7 usec */
if ( locomo_readl ( mapbase + LOCOMO_DAC ) & LOCOMO_DAC_SDAOEB ) { /* High is error */
printk ( KERN_WARNING " locomo: m62332_senddata Error 2 \n " ) ;
return ;
}
/* Send DAC data */
for ( i = 1 ; i < = 8 ; i + + ) {
locomo_m62332_sendbit ( mapbase , dac_data > > ( 8 - i ) ) ;
}
/* Check A bit */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SCLOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
udelay ( DAC_SCL_LOW_HOLD_TIME ) ; /* 4.7 usec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SDAOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SCLOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_HIGH_SETUP_TIME ) ; /* 1000 nsec */
udelay ( DAC_SCL_HIGH_HOLD_TIME ) ; /* 4.7 usec */
if ( locomo_readl ( mapbase + LOCOMO_DAC ) & LOCOMO_DAC_SDAOEB ) { /* High is error */
printk ( KERN_WARNING " locomo: m62332_senddata Error 3 \n " ) ;
return ;
}
/* stop */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r & = ~ ( LOCOMO_DAC_SCLOEB ) ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 300 nsec */
udelay ( DAC_SCL_LOW_HOLD_TIME ) ; /* 4.7 usec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SCLOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_HIGH_SETUP_TIME ) ; /* 1000 nsec */
udelay ( DAC_SCL_HIGH_HOLD_TIME ) ; /* 4 usec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SDAOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_HIGH_SETUP_TIME ) ; /* 1000 nsec */
udelay ( DAC_SCL_HIGH_HOLD_TIME ) ; /* 4 usec */
r = locomo_readl ( mapbase + LOCOMO_DAC ) ;
r | = LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB ;
locomo_writel ( r , mapbase + LOCOMO_DAC ) ;
udelay ( DAC_LOW_SETUP_TIME ) ; /* 1000 nsec */
udelay ( DAC_SCL_LOW_HOLD_TIME ) ; /* 4.7 usec */
spin_unlock_irqrestore ( & lchip - > lock , flags ) ;
}
/*
* LoCoMo " Register Access Bus. "
*
* We model this as a regular bus type , and hang devices directly
* off this .
*/
static int locomo_match ( struct device * _dev , struct device_driver * _drv )
{
struct locomo_dev * dev = LOCOMO_DEV ( _dev ) ;
struct locomo_driver * drv = LOCOMO_DRV ( _drv ) ;
return dev - > devid = = drv - > devid ;
}
static int locomo_bus_suspend ( struct device * dev , pm_message_t state )
{
struct locomo_dev * ldev = LOCOMO_DEV ( dev ) ;
struct locomo_driver * drv = LOCOMO_DRV ( dev - > driver ) ;
int ret = 0 ;
if ( drv & & drv - > suspend )
ret = drv - > suspend ( ldev , state ) ;
return ret ;
}
static int locomo_bus_resume ( struct device * dev )
{
struct locomo_dev * ldev = LOCOMO_DEV ( dev ) ;
struct locomo_driver * drv = LOCOMO_DRV ( dev - > driver ) ;
int ret = 0 ;
if ( drv & & drv - > resume )
ret = drv - > resume ( ldev ) ;
return ret ;
}
static int locomo_bus_probe ( struct device * dev )
{
struct locomo_dev * ldev = LOCOMO_DEV ( dev ) ;
struct locomo_driver * drv = LOCOMO_DRV ( dev - > driver ) ;
int ret = - ENODEV ;
if ( drv - > probe )
ret = drv - > probe ( ldev ) ;
return ret ;
}
static int locomo_bus_remove ( struct device * dev )
{
struct locomo_dev * ldev = LOCOMO_DEV ( dev ) ;
struct locomo_driver * drv = LOCOMO_DRV ( dev - > driver ) ;
int ret = 0 ;
if ( drv - > remove )
ret = drv - > remove ( ldev ) ;
return ret ;
}
struct bus_type locomo_bus_type = {
. name = " locomo-bus " ,
. match = locomo_match ,
2006-01-05 17:33:04 +03:00
. probe = locomo_bus_probe ,
. remove = locomo_bus_remove ,
2005-04-17 02:20:36 +04:00
. suspend = locomo_bus_suspend ,
. resume = locomo_bus_resume ,
} ;
int locomo_driver_register ( struct locomo_driver * driver )
{
driver - > drv . bus = & locomo_bus_type ;
return driver_register ( & driver - > drv ) ;
}
void locomo_driver_unregister ( struct locomo_driver * driver )
{
driver_unregister ( & driver - > drv ) ;
}
static int __init locomo_init ( void )
{
int ret = bus_register ( & locomo_bus_type ) ;
if ( ret = = 0 )
2005-11-10 01:32:44 +03:00
platform_driver_register ( & locomo_device_driver ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
static void __exit locomo_exit ( void )
{
2005-11-10 01:32:44 +03:00
platform_driver_unregister ( & locomo_device_driver ) ;
2005-04-17 02:20:36 +04:00
bus_unregister ( & locomo_bus_type ) ;
}
module_init ( locomo_init ) ;
module_exit ( locomo_exit ) ;
MODULE_DESCRIPTION ( " Sharp LoCoMo core driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " John Lenz <lenz@cs.wisc.edu> " ) ;
EXPORT_SYMBOL ( locomo_driver_register ) ;
EXPORT_SYMBOL ( locomo_driver_unregister ) ;
EXPORT_SYMBOL ( locomo_gpio_set_dir ) ;
EXPORT_SYMBOL ( locomo_gpio_read_level ) ;
EXPORT_SYMBOL ( locomo_gpio_read_output ) ;
EXPORT_SYMBOL ( locomo_gpio_write ) ;
EXPORT_SYMBOL ( locomo_m62332_senddata ) ;