📄 corgi_ssp.c
字号:
/* * SSP control code for Sharp Corgi devices * * Copyright (c) 2004-2005 Richard Purdie * * 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. * */#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <asm/hardware.h>#include <asm/mach-types.h>#include <asm/arch/ssp.h>#include <asm/arch/pxa-regs.h>#include "sharpsl.h"static DEFINE_SPINLOCK(corgi_ssp_lock);static struct ssp_dev corgi_ssp_dev;static struct ssp_state corgi_ssp_state;static struct corgissp_machinfo *ssp_machinfo;/* * There are three devices connected to the SSP interface: * 1. A touchscreen controller (TI ADS7846 compatible) * 2. An LCD contoller (with some Backlight functionality) * 3. A battery moinitoring IC (Maxim MAX1111) * * Each device uses a different speed/mode of communication. * * The touchscreen is very sensitive and the most frequently used * so the port is left configured for this. * * Devices are selected using Chip Selects on GPIOs. *//* * ADS7846 Routines */unsigned long corgi_ssp_ads7846_putget(ulong data){ unsigned long ret,flag; spin_lock_irqsave(&corgi_ssp_lock, flag); GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); ssp_write_word(&corgi_ssp_dev,data); ret = ssp_read_word(&corgi_ssp_dev); GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); spin_unlock_irqrestore(&corgi_ssp_lock, flag); return ret;}/* * NOTE: These functions should always be called in interrupt context * and use the _lock and _unlock functions. They are very time sensitive. */void corgi_ssp_ads7846_lock(void){ spin_lock(&corgi_ssp_lock); GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);}void corgi_ssp_ads7846_unlock(void){ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); spin_unlock(&corgi_ssp_lock);}void corgi_ssp_ads7846_put(ulong data){ ssp_write_word(&corgi_ssp_dev,data);}unsigned long corgi_ssp_ads7846_get(void){ return ssp_read_word(&corgi_ssp_dev);}EXPORT_SYMBOL(corgi_ssp_ads7846_putget);EXPORT_SYMBOL(corgi_ssp_ads7846_lock);EXPORT_SYMBOL(corgi_ssp_ads7846_unlock);EXPORT_SYMBOL(corgi_ssp_ads7846_put);EXPORT_SYMBOL(corgi_ssp_ads7846_get);/* * LCD/Backlight Routines */unsigned long corgi_ssp_dac_put(ulong data){ unsigned long flag, sscr1 = SSCR1_SPH; spin_lock_irqsave(&corgi_ssp_lock, flag); if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) sscr1 = 0; ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon)); ssp_enable(&corgi_ssp_dev); GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); ssp_write_word(&corgi_ssp_dev,data); /* Read null data back from device to prevent SSP overflow */ ssp_read_word(&corgi_ssp_dev); GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); ssp_enable(&corgi_ssp_dev); spin_unlock_irqrestore(&corgi_ssp_lock, flag); return 0;}void corgi_ssp_lcdtg_send(u8 adrs, u8 data){ corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f));}void corgi_ssp_blduty_set(int duty){ corgi_ssp_lcdtg_send(0x02,duty);}EXPORT_SYMBOL(corgi_ssp_lcdtg_send);EXPORT_SYMBOL(corgi_ssp_blduty_set);/* * Max1111 Routines */int corgi_ssp_max1111_get(ulong data){ unsigned long flag; int voltage,voltage1,voltage2; spin_lock_irqsave(&corgi_ssp_lock, flag); GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111)); ssp_enable(&corgi_ssp_dev); udelay(1); /* TB1/RB1 */ ssp_write_word(&corgi_ssp_dev,data); ssp_read_word(&corgi_ssp_dev); /* null read */ /* TB12/RB2 */ ssp_write_word(&corgi_ssp_dev,0); voltage1=ssp_read_word(&corgi_ssp_dev); /* TB13/RB3*/ ssp_write_word(&corgi_ssp_dev,0); voltage2=ssp_read_word(&corgi_ssp_dev); ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); ssp_enable(&corgi_ssp_dev); GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); spin_unlock_irqrestore(&corgi_ssp_lock, flag); if (voltage1 & 0xc0 || voltage2 & 0x3f) voltage = -1; else voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03); return voltage;}EXPORT_SYMBOL(corgi_ssp_max1111_get);/* * Support Routines */void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo){ ssp_machinfo = machinfo;}static int __init corgi_ssp_probe(struct platform_device *dev){ int ret; /* Chip Select - Disable All */ GPDR(ssp_machinfo->cs_lcdcon) |= GPIO_bit(ssp_machinfo->cs_lcdcon); /* output */ GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ GPDR(ssp_machinfo->cs_max1111) |= GPIO_bit(ssp_machinfo->cs_max1111); /* output */ GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/ GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0); if (ret) printk(KERN_ERR "Unable to register SSP handler!\n"); else { ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); ssp_enable(&corgi_ssp_dev); } return ret;}static int corgi_ssp_remove(struct platform_device *dev){ ssp_exit(&corgi_ssp_dev); return 0;}static int corgi_ssp_suspend(struct platform_device *dev, pm_message_t state){ ssp_flush(&corgi_ssp_dev); ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state); return 0;}static int corgi_ssp_resume(struct platform_device *dev){ GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state); ssp_enable(&corgi_ssp_dev); return 0;}static struct platform_driver corgissp_driver = { .probe = corgi_ssp_probe, .remove = corgi_ssp_remove, .suspend = corgi_ssp_suspend, .resume = corgi_ssp_resume, .driver = { .name = "corgi-ssp", },};int __init corgi_ssp_init(void){ return platform_driver_register(&corgissp_driver);}arch_initcall(corgi_ssp_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -