forked from luck/tmp_suning_uos_patched
Merge branch 'pxa-tosa' into pxa
Conflicts: arch/arm/mach-pxa/Kconfig arch/arm/mach-pxa/tosa.c arch/arm/mach-pxa/spitz.c
This commit is contained in:
commit
7fecc34e07
|
@ -584,6 +584,8 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
|
|||
S: Maintained
|
||||
|
||||
ARM/TOSA MACHINE SUPPORT
|
||||
P: Dmitry Baryshkov
|
||||
M: dbaryshkov@gmail.com
|
||||
P: Dirk Opfer
|
||||
M: dirk@opfer-online.de
|
||||
S: Maintained
|
||||
|
|
|
@ -310,4 +310,13 @@ config PXA_PWM
|
|||
default BACKLIGHT_PWM
|
||||
help
|
||||
Enable support for PXA2xx/PXA3xx PWM controllers
|
||||
|
||||
config TOSA_BT
|
||||
tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
|
||||
depends on MACH_TOSA
|
||||
select RFKILL
|
||||
help
|
||||
This is a simple driver that is able to control
|
||||
the state of built in bluetooth chip on tosa.
|
||||
|
||||
endif
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# Common support (must be linked before board specific support)
|
||||
obj-y += clock.o devices.o generic.o irq.o dma.o \
|
||||
time.o gpio.o
|
||||
time.o gpio.o reset.o
|
||||
obj-$(CONFIG_PM) += pm.o sleep.o standby.o
|
||||
obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o
|
||||
|
||||
|
@ -61,3 +61,5 @@ obj-$(CONFIG_LEDS) += $(led-y)
|
|||
ifeq ($(CONFIG_PCI),y)
|
||||
obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_TOSA_BT) += tosa-bt.o
|
||||
|
|
96
arch/arm/mach-pxa/reset.c
Normal file
96
arch/arm/mach-pxa/reset.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/proc-fns.h>
|
||||
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/pxa2xx-regs.h>
|
||||
|
||||
static void do_hw_reset(void);
|
||||
|
||||
static int reset_gpio = -1;
|
||||
|
||||
int init_gpio_reset(int gpio)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = gpio_request(gpio, "reset generator");
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Can't request reset_gpio\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = gpio_direction_input(gpio);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Can't configure reset_gpio for input\n");
|
||||
gpio_free(gpio);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (!rc)
|
||||
reset_gpio = gpio;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Trigger GPIO reset.
|
||||
* This covers various types of logic connecting gpio pin
|
||||
* to RESET pins (nRESET or GPIO_RESET):
|
||||
*/
|
||||
static void do_gpio_reset(void)
|
||||
{
|
||||
BUG_ON(reset_gpio == -1);
|
||||
|
||||
/* drive it low */
|
||||
gpio_direction_output(reset_gpio, 0);
|
||||
mdelay(2);
|
||||
/* rising edge or drive high */
|
||||
gpio_set_value(reset_gpio, 1);
|
||||
mdelay(2);
|
||||
/* falling edge */
|
||||
gpio_set_value(reset_gpio, 0);
|
||||
|
||||
/* give it some time */
|
||||
mdelay(10);
|
||||
|
||||
WARN_ON(1);
|
||||
/* fallback */
|
||||
do_hw_reset();
|
||||
}
|
||||
|
||||
static void do_hw_reset(void)
|
||||
{
|
||||
/* Initialize the watchdog and let it fire */
|
||||
OWER = OWER_WME;
|
||||
OSSR = OSSR_M3;
|
||||
OSMR3 = OSCR + 368640; /* ... in 100 ms */
|
||||
}
|
||||
|
||||
void arch_reset(char mode)
|
||||
{
|
||||
if (cpu_is_pxa2xx())
|
||||
RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
|
||||
|
||||
switch (mode) {
|
||||
case 's':
|
||||
/* Jump into ROM at address 0 */
|
||||
cpu_reset(0);
|
||||
break;
|
||||
case 'h':
|
||||
do_hw_reset();
|
||||
break;
|
||||
case 'g':
|
||||
do_gpio_reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@
|
|||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/pxa2xx-regs.h>
|
||||
#include <asm/arch/pxa2xx-gpio.h>
|
||||
#include <asm/arch/pxa27x-udc.h>
|
||||
#include <asm/arch/irda.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
|
@ -529,11 +530,7 @@ static struct platform_device *devices[] __initdata = {
|
|||
|
||||
static void spitz_poweroff(void)
|
||||
{
|
||||
pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT);
|
||||
GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET);
|
||||
|
||||
mdelay(1000);
|
||||
arm_machine_restart('h');
|
||||
arm_machine_restart('g');
|
||||
}
|
||||
|
||||
static void spitz_restart(char mode)
|
||||
|
@ -547,6 +544,7 @@ static void spitz_restart(char mode)
|
|||
|
||||
static void __init common_init(void)
|
||||
{
|
||||
init_gpio_reset(SPITZ_GPIO_ON_RESET);
|
||||
pm_power_off = spitz_poweroff;
|
||||
arm_pm_restart = spitz_restart;
|
||||
|
||||
|
|
150
arch/arm/mach-pxa/tosa-bt.c
Normal file
150
arch/arm/mach-pxa/tosa-bt.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Bluetooth built-in chip control
|
||||
*
|
||||
* Copyright (c) 2008 Dmitry Baryshkov
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/rfkill.h>
|
||||
|
||||
#include <asm/arch/tosa_bt.h>
|
||||
|
||||
static void tosa_bt_on(struct tosa_bt_data *data)
|
||||
{
|
||||
gpio_set_value(data->gpio_reset, 0);
|
||||
gpio_set_value(data->gpio_pwr, 1);
|
||||
gpio_set_value(data->gpio_reset, 1);
|
||||
mdelay(20);
|
||||
gpio_set_value(data->gpio_reset, 0);
|
||||
}
|
||||
|
||||
static void tosa_bt_off(struct tosa_bt_data *data)
|
||||
{
|
||||
gpio_set_value(data->gpio_reset, 1);
|
||||
mdelay(10);
|
||||
gpio_set_value(data->gpio_pwr, 0);
|
||||
gpio_set_value(data->gpio_reset, 0);
|
||||
}
|
||||
|
||||
static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
|
||||
{
|
||||
pr_info("BT_RADIO going: %s\n",
|
||||
state == RFKILL_STATE_ON ? "on" : "off");
|
||||
|
||||
if (state == RFKILL_STATE_ON) {
|
||||
pr_info("TOSA_BT: going ON\n");
|
||||
tosa_bt_on(data);
|
||||
} else {
|
||||
pr_info("TOSA_BT: going OFF\n");
|
||||
tosa_bt_off(data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tosa_bt_probe(struct platform_device *dev)
|
||||
{
|
||||
int rc;
|
||||
struct rfkill *rfk;
|
||||
|
||||
struct tosa_bt_data *data = dev->dev.platform_data;
|
||||
|
||||
rc = gpio_request(data->gpio_reset, "Bluetooth reset");
|
||||
if (rc)
|
||||
goto err_reset;
|
||||
rc = gpio_direction_output(data->gpio_reset, 0);
|
||||
if (rc)
|
||||
goto err_reset_dir;
|
||||
rc = gpio_request(data->gpio_pwr, "Bluetooth power");
|
||||
if (rc)
|
||||
goto err_pwr;
|
||||
rc = gpio_direction_output(data->gpio_pwr, 0);
|
||||
if (rc)
|
||||
goto err_pwr_dir;
|
||||
|
||||
rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
|
||||
if (!rfk) {
|
||||
rc = -ENOMEM;
|
||||
goto err_rfk_alloc;
|
||||
}
|
||||
|
||||
rfk->name = "tosa-bt";
|
||||
rfk->toggle_radio = tosa_bt_toggle_radio;
|
||||
rfk->data = data;
|
||||
#ifdef CONFIG_RFKILL_LEDS
|
||||
rfk->led_trigger.name = "tosa-bt";
|
||||
#endif
|
||||
|
||||
rc = rfkill_register(rfk);
|
||||
if (rc)
|
||||
goto err_rfkill;
|
||||
|
||||
platform_set_drvdata(dev, rfk);
|
||||
|
||||
return 0;
|
||||
|
||||
err_rfkill:
|
||||
if (rfk)
|
||||
rfkill_free(rfk);
|
||||
rfk = NULL;
|
||||
err_rfk_alloc:
|
||||
tosa_bt_off(data);
|
||||
err_pwr_dir:
|
||||
gpio_free(data->gpio_pwr);
|
||||
err_pwr:
|
||||
err_reset_dir:
|
||||
gpio_free(data->gpio_reset);
|
||||
err_reset:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __devexit tosa_bt_remove(struct platform_device *dev)
|
||||
{
|
||||
struct tosa_bt_data *data = dev->dev.platform_data;
|
||||
struct rfkill *rfk = platform_get_drvdata(dev);
|
||||
|
||||
platform_set_drvdata(dev, NULL);
|
||||
|
||||
if (rfk)
|
||||
rfkill_unregister(rfk);
|
||||
rfk = NULL;
|
||||
|
||||
tosa_bt_off(data);
|
||||
|
||||
gpio_free(data->gpio_pwr);
|
||||
gpio_free(data->gpio_reset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver tosa_bt_driver = {
|
||||
.probe = tosa_bt_probe,
|
||||
.remove = __devexit_p(tosa_bt_remove),
|
||||
|
||||
.driver = {
|
||||
.name = "tosa-bt",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static int __init tosa_bt_init(void)
|
||||
{
|
||||
return platform_driver_register(&tosa_bt_driver);
|
||||
}
|
||||
|
||||
static void __exit tosa_bt_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tosa_bt_driver);
|
||||
}
|
||||
|
||||
module_init(tosa_bt_init);
|
||||
module_exit(tosa_bt_exit);
|
|
@ -18,30 +18,31 @@
|
|||
#include <linux/major.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mfd/tc6393xb.h>
|
||||
#include <linux/mfd/tmio.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pda_power.h>
|
||||
#include <linux/rfkill.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/pxa2xx-regs.h>
|
||||
#include <asm/arch/mfp-pxa25x.h>
|
||||
#include <asm/arch/irda.h>
|
||||
#include <asm/arch/i2c.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/udc.h>
|
||||
#include <asm/arch/tosa_bt.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/arch/tosa.h>
|
||||
|
||||
#include <asm/hardware/scoop.h>
|
||||
|
@ -86,7 +87,7 @@ static unsigned long tosa_pin_config[] = {
|
|||
GPIO6_MMC_CLK,
|
||||
GPIO8_MMC_CS0,
|
||||
GPIO9_GPIO, /* Detect */
|
||||
// GPIO10 nSD_INT
|
||||
GPIO10_GPIO, /* nSD_INT */
|
||||
|
||||
/* CF */
|
||||
GPIO13_GPIO, /* CD_IRQ */
|
||||
|
@ -124,29 +125,25 @@ static unsigned long tosa_pin_config[] = {
|
|||
GPIO44_BTUART_CTS,
|
||||
GPIO45_BTUART_RTS,
|
||||
|
||||
/* IrDA */
|
||||
GPIO46_STUART_RXD,
|
||||
GPIO47_STUART_TXD,
|
||||
|
||||
/* Keybd */
|
||||
GPIO58_GPIO,
|
||||
GPIO59_GPIO,
|
||||
GPIO60_GPIO,
|
||||
GPIO61_GPIO,
|
||||
GPIO62_GPIO,
|
||||
GPIO63_GPIO,
|
||||
GPIO64_GPIO,
|
||||
GPIO65_GPIO,
|
||||
GPIO66_GPIO,
|
||||
GPIO67_GPIO,
|
||||
GPIO68_GPIO,
|
||||
GPIO69_GPIO,
|
||||
GPIO70_GPIO,
|
||||
GPIO71_GPIO,
|
||||
GPIO72_GPIO,
|
||||
GPIO73_GPIO,
|
||||
GPIO74_GPIO,
|
||||
GPIO75_GPIO,
|
||||
GPIO58_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO59_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO60_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO61_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO62_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO63_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO64_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO65_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO66_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO67_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO68_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO69_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO70_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO71_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO72_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO73_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO74_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
GPIO75_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
|
||||
/* SPI */
|
||||
GPIO81_SSP2_CLK_OUT,
|
||||
|
@ -154,6 +151,17 @@ static unsigned long tosa_pin_config[] = {
|
|||
GPIO83_SSP2_TXD,
|
||||
};
|
||||
|
||||
static unsigned long tosa_pin_irda_off[] = {
|
||||
GPIO46_STUART_RXD,
|
||||
GPIO47_GPIO | MFP_LPM_DRIVE_LOW,
|
||||
};
|
||||
|
||||
static unsigned long tosa_pin_irda_on[] = {
|
||||
GPIO46_STUART_RXD,
|
||||
GPIO47_STUART_TXD,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* SCOOP Device
|
||||
*/
|
||||
|
@ -249,6 +257,15 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
|
|||
|
||||
tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250);
|
||||
|
||||
err = gpio_request(TOSA_GPIO_nSD_DETECT, "MMC/SD card detect");
|
||||
if (err) {
|
||||
printk(KERN_ERR "tosa_mci_init: can't request nSD_DETECT gpio\n");
|
||||
goto err_gpio_detect;
|
||||
}
|
||||
err = gpio_direction_input(TOSA_GPIO_nSD_DETECT);
|
||||
if (err)
|
||||
goto err_gpio_detect_dir;
|
||||
|
||||
err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||
"MMC/SD card detect", data);
|
||||
|
@ -257,7 +274,7 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
|
|||
goto err_irq;
|
||||
}
|
||||
|
||||
err = gpio_request(TOSA_GPIO_SD_WP, "sd_wp");
|
||||
err = gpio_request(TOSA_GPIO_SD_WP, "SD Write Protect");
|
||||
if (err) {
|
||||
printk(KERN_ERR "tosa_mci_init: can't request SD_WP gpio\n");
|
||||
goto err_gpio_wp;
|
||||
|
@ -266,7 +283,7 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
|
|||
if (err)
|
||||
goto err_gpio_wp_dir;
|
||||
|
||||
err = gpio_request(TOSA_GPIO_PWR_ON, "sd_pwr");
|
||||
err = gpio_request(TOSA_GPIO_PWR_ON, "SD Power");
|
||||
if (err) {
|
||||
printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
|
||||
goto err_gpio_pwr;
|
||||
|
@ -275,8 +292,20 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
|
|||
if (err)
|
||||
goto err_gpio_pwr_dir;
|
||||
|
||||
err = gpio_request(TOSA_GPIO_nSD_INT, "SD Int");
|
||||
if (err) {
|
||||
printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
|
||||
goto err_gpio_int;
|
||||
}
|
||||
err = gpio_direction_input(TOSA_GPIO_nSD_INT);
|
||||
if (err)
|
||||
goto err_gpio_int_dir;
|
||||
|
||||
return 0;
|
||||
|
||||
err_gpio_int_dir:
|
||||
gpio_free(TOSA_GPIO_nSD_INT);
|
||||
err_gpio_int:
|
||||
err_gpio_pwr_dir:
|
||||
gpio_free(TOSA_GPIO_PWR_ON);
|
||||
err_gpio_pwr:
|
||||
|
@ -285,6 +314,9 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
|
|||
err_gpio_wp:
|
||||
free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
|
||||
err_irq:
|
||||
err_gpio_detect_dir:
|
||||
gpio_free(TOSA_GPIO_nSD_DETECT);
|
||||
err_gpio_detect:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -306,9 +338,11 @@ static int tosa_mci_get_ro(struct device *dev)
|
|||
|
||||
static void tosa_mci_exit(struct device *dev, void *data)
|
||||
{
|
||||
gpio_free(TOSA_GPIO_nSD_INT);
|
||||
gpio_free(TOSA_GPIO_PWR_ON);
|
||||
gpio_free(TOSA_GPIO_SD_WP);
|
||||
free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
|
||||
gpio_free(TOSA_GPIO_nSD_DETECT);
|
||||
}
|
||||
|
||||
static struct pxamci_platform_data tosa_mci_platform_data = {
|
||||
|
@ -322,29 +356,55 @@ static struct pxamci_platform_data tosa_mci_platform_data = {
|
|||
/*
|
||||
* Irda
|
||||
*/
|
||||
static void tosa_irda_transceiver_mode(struct device *dev, int mode)
|
||||
{
|
||||
if (mode & IR_OFF) {
|
||||
gpio_set_value(TOSA_GPIO_IR_POWERDWN, 0);
|
||||
pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_off));
|
||||
gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
|
||||
} else {
|
||||
pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_on));
|
||||
gpio_set_value(TOSA_GPIO_IR_POWERDWN, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int tosa_irda_startup(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_request(TOSA_GPIO_IRDA_TX, "IrDA TX");
|
||||
if (ret)
|
||||
goto err_tx;
|
||||
ret = gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
|
||||
if (ret)
|
||||
goto err_tx_dir;
|
||||
|
||||
ret = gpio_request(TOSA_GPIO_IR_POWERDWN, "IrDA powerdown");
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_pwr;
|
||||
|
||||
ret = gpio_direction_output(TOSA_GPIO_IR_POWERDWN, 0);
|
||||
if (ret)
|
||||
gpio_free(TOSA_GPIO_IR_POWERDWN);
|
||||
goto err_pwr_dir;
|
||||
|
||||
tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
|
||||
|
||||
return 0;
|
||||
|
||||
err_pwr_dir:
|
||||
gpio_free(TOSA_GPIO_IR_POWERDWN);
|
||||
err_pwr:
|
||||
err_tx_dir:
|
||||
gpio_free(TOSA_GPIO_IRDA_TX);
|
||||
err_tx:
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static void tosa_irda_shutdown(struct device *dev)
|
||||
{
|
||||
tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
|
||||
gpio_free(TOSA_GPIO_IR_POWERDWN);
|
||||
}
|
||||
|
||||
static void tosa_irda_transceiver_mode(struct device *dev, int mode)
|
||||
{
|
||||
gpio_set_value(TOSA_GPIO_IR_POWERDWN, !(mode & IR_OFF));
|
||||
gpio_free(TOSA_GPIO_IRDA_TX);
|
||||
}
|
||||
|
||||
static struct pxaficp_platform_data tosa_ficp_platform_data = {
|
||||
|
@ -354,6 +414,70 @@ static struct pxaficp_platform_data tosa_ficp_platform_data = {
|
|||
.shutdown = tosa_irda_shutdown,
|
||||
};
|
||||
|
||||
/*
|
||||
* Tosa AC IN
|
||||
*/
|
||||
static int tosa_power_init(struct device *dev)
|
||||
{
|
||||
int ret = gpio_request(TOSA_GPIO_AC_IN, "ac in");
|
||||
if (ret)
|
||||
goto err_gpio_req;
|
||||
|
||||
ret = gpio_direction_input(TOSA_GPIO_AC_IN);
|
||||
if (ret)
|
||||
goto err_gpio_in;
|
||||
|
||||
return 0;
|
||||
|
||||
err_gpio_in:
|
||||
gpio_free(TOSA_GPIO_AC_IN);
|
||||
err_gpio_req:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tosa_power_exit(struct device *dev)
|
||||
{
|
||||
gpio_free(TOSA_GPIO_AC_IN);
|
||||
}
|
||||
|
||||
static int tosa_power_ac_online(void)
|
||||
{
|
||||
return gpio_get_value(TOSA_GPIO_AC_IN) == 0;
|
||||
}
|
||||
|
||||
static char *tosa_ac_supplied_to[] = {
|
||||
"main-battery",
|
||||
"backup-battery",
|
||||
"jacket-battery",
|
||||
};
|
||||
|
||||
static struct pda_power_pdata tosa_power_data = {
|
||||
.init = tosa_power_init,
|
||||
.is_ac_online = tosa_power_ac_online,
|
||||
.exit = tosa_power_exit,
|
||||
.supplied_to = tosa_ac_supplied_to,
|
||||
.num_supplicants = ARRAY_SIZE(tosa_ac_supplied_to),
|
||||
};
|
||||
|
||||
static struct resource tosa_power_resource[] = {
|
||||
{
|
||||
.name = "ac",
|
||||
.start = gpio_to_irq(TOSA_GPIO_AC_IN),
|
||||
.end = gpio_to_irq(TOSA_GPIO_AC_IN),
|
||||
.flags = IORESOURCE_IRQ |
|
||||
IORESOURCE_IRQ_HIGHEDGE |
|
||||
IORESOURCE_IRQ_LOWEDGE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device tosa_power_device = {
|
||||
.name = "pda-power",
|
||||
.id = -1,
|
||||
.dev.platform_data = &tosa_power_data,
|
||||
.resource = tosa_power_resource,
|
||||
.num_resources = ARRAY_SIZE(tosa_power_resource),
|
||||
};
|
||||
|
||||
/*
|
||||
* Tosa Keyboard
|
||||
*/
|
||||
|
@ -439,7 +563,7 @@ static struct gpio_led tosa_gpio_leds[] = {
|
|||
},
|
||||
{
|
||||
.name = "tosa:blue:bluetooth",
|
||||
.default_trigger = "none",
|
||||
.default_trigger = "tosa-bt",
|
||||
.gpio = TOSA_GPIO_BT_LED,
|
||||
},
|
||||
};
|
||||
|
@ -457,21 +581,184 @@ static struct platform_device tosaled_device = {
|
|||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Toshiba Mobile IO Controller
|
||||
*/
|
||||
static struct resource tc6393xb_resources[] = {
|
||||
[0] = {
|
||||
.start = TOSA_LCDC_PHYS,
|
||||
.end = TOSA_LCDC_PHYS + 0x3ffffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
|
||||
[1] = {
|
||||
.start = TOSA_IRQ_GPIO_TC6393XB_INT,
|
||||
.end = TOSA_IRQ_GPIO_TC6393XB_INT,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static int tosa_tc6393xb_enable(struct platform_device *dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = gpio_request(TOSA_GPIO_TC6393XB_REST_IN, "tc6393xb #pclr");
|
||||
if (rc)
|
||||
goto err_req_pclr;
|
||||
rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend");
|
||||
if (rc)
|
||||
goto err_req_suspend;
|
||||
rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "l3v");
|
||||
if (rc)
|
||||
goto err_req_l3v;
|
||||
rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0);
|
||||
if (rc)
|
||||
goto err_dir_l3v;
|
||||
rc = gpio_direction_output(TOSA_GPIO_TC6393XB_SUSPEND, 0);
|
||||
if (rc)
|
||||
goto err_dir_suspend;
|
||||
rc = gpio_direction_output(TOSA_GPIO_TC6393XB_REST_IN, 0);
|
||||
if (rc)
|
||||
goto err_dir_pclr;
|
||||
|
||||
mdelay(1);
|
||||
|
||||
gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
|
||||
|
||||
mdelay(10);
|
||||
|
||||
gpio_set_value(TOSA_GPIO_TC6393XB_REST_IN, 1);
|
||||
gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
|
||||
|
||||
return 0;
|
||||
err_dir_pclr:
|
||||
err_dir_suspend:
|
||||
err_dir_l3v:
|
||||
gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
|
||||
err_req_l3v:
|
||||
gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
|
||||
err_req_suspend:
|
||||
gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
|
||||
err_req_pclr:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tosa_tc6393xb_disable(struct platform_device *dev)
|
||||
{
|
||||
gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
|
||||
gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
|
||||
gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tosa_tc6393xb_resume(struct platform_device *dev)
|
||||
{
|
||||
gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
|
||||
mdelay(10);
|
||||
gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
|
||||
mdelay(10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tosa_tc6393xb_suspend(struct platform_device *dev)
|
||||
{
|
||||
gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 0);
|
||||
gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mtd_partition tosa_nand_partition[] = {
|
||||
{
|
||||
.name = "smf",
|
||||
.offset = 0,
|
||||
.size = 7 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "root",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = 28 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "home",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
},
|
||||
};
|
||||
|
||||
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
||||
|
||||
static struct nand_bbt_descr tosa_tc6393xb_nand_bbt = {
|
||||
.options = 0,
|
||||
.offs = 4,
|
||||
.len = 2,
|
||||
.pattern = scan_ff_pattern
|
||||
};
|
||||
|
||||
static struct tmio_nand_data tosa_tc6393xb_nand_config = {
|
||||
.num_partitions = ARRAY_SIZE(tosa_nand_partition),
|
||||
.partition = tosa_nand_partition,
|
||||
.badblock_pattern = &tosa_tc6393xb_nand_bbt,
|
||||
};
|
||||
|
||||
static struct tc6393xb_platform_data tosa_tc6393xb_setup = {
|
||||
.scr_pll2cr = 0x0cc1,
|
||||
.scr_gper = 0x3300,
|
||||
.scr_gpo_dsr =
|
||||
TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
|
||||
.scr_gpo_doecr =
|
||||
TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
|
||||
|
||||
.irq_base = IRQ_BOARD_START,
|
||||
.gpio_base = TOSA_TC6393XB_GPIO_BASE,
|
||||
|
||||
.enable = tosa_tc6393xb_enable,
|
||||
.disable = tosa_tc6393xb_disable,
|
||||
.suspend = tosa_tc6393xb_suspend,
|
||||
.resume = tosa_tc6393xb_resume,
|
||||
|
||||
.nand_data = &tosa_tc6393xb_nand_config,
|
||||
};
|
||||
|
||||
|
||||
static struct platform_device tc6393xb_device = {
|
||||
.name = "tc6393xb",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &tosa_tc6393xb_setup,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(tc6393xb_resources),
|
||||
.resource = tc6393xb_resources,
|
||||
};
|
||||
|
||||
static struct tosa_bt_data tosa_bt_data = {
|
||||
.gpio_pwr = TOSA_GPIO_BT_PWR_EN,
|
||||
.gpio_reset = TOSA_GPIO_BT_RESET,
|
||||
};
|
||||
|
||||
static struct platform_device tosa_bt_device = {
|
||||
.name = "tosa-bt",
|
||||
.id = -1,
|
||||
.dev.platform_data = &tosa_bt_data,
|
||||
};
|
||||
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&tosascoop_device,
|
||||
&tosascoop_jc_device,
|
||||
&tc6393xb_device,
|
||||
&tosa_power_device,
|
||||
&tosakbd_device,
|
||||
&tosa_gpio_keys_device,
|
||||
&tosaled_device,
|
||||
&tosa_bt_device,
|
||||
};
|
||||
|
||||
static void tosa_poweroff(void)
|
||||
{
|
||||
gpio_direction_output(TOSA_GPIO_ON_RESET, 0);
|
||||
gpio_set_value(TOSA_GPIO_ON_RESET, 1);
|
||||
|
||||
mdelay(1000);
|
||||
arm_machine_restart('h');
|
||||
arm_machine_restart('g');
|
||||
}
|
||||
|
||||
static void tosa_restart(char mode)
|
||||
|
@ -485,10 +772,15 @@ static void tosa_restart(char mode)
|
|||
|
||||
static void __init tosa_init(void)
|
||||
{
|
||||
int dummy;
|
||||
|
||||
pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
|
||||
pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_off));
|
||||
gpio_set_wake(MFP_PIN_GPIO1, 1);
|
||||
/* We can't pass to gpio-keys since it will drop the Reset altfunc */
|
||||
|
||||
init_gpio_reset(TOSA_GPIO_ON_RESET);
|
||||
|
||||
pm_power_off = tosa_poweroff;
|
||||
arm_pm_restart = tosa_restart;
|
||||
|
||||
|
@ -497,6 +789,10 @@ static void __init tosa_init(void)
|
|||
/* enable batt_fault */
|
||||
PMCR = 0x01;
|
||||
|
||||
dummy = gpiochip_reserve(TOSA_SCOOP_GPIO_BASE, 12);
|
||||
dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12);
|
||||
dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16);
|
||||
|
||||
pxa_set_mci_info(&tosa_mci_platform_data);
|
||||
pxa_set_udc_info(&udc_info);
|
||||
pxa_set_ficp_info(&tosa_ficp_platform_data);
|
||||
|
|
|
@ -215,8 +215,6 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tosakbd->lock, flags);
|
||||
PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
|
||||
PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT);
|
||||
tosakbd->suspended = 1;
|
||||
spin_unlock_irqrestore(&tosakbd->lock, flags);
|
||||
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
menu "Multifunction device drivers"
|
||||
depends on HAS_IOMEM
|
||||
|
||||
config MFD_CORE
|
||||
tristate
|
||||
default n
|
||||
|
||||
config MFD_SM501
|
||||
tristate "Support for Silicon Motion SM501"
|
||||
---help---
|
||||
|
@ -38,6 +42,13 @@ config HTC_PASIC3
|
|||
HTC Magician devices, respectively. Actual functionality is
|
||||
handled by the leds-pasic3 and ds1wm drivers.
|
||||
|
||||
config MFD_TC6393XB
|
||||
bool "Support Toshiba TC6393XB"
|
||||
depends on HAVE_GPIO_LIB
|
||||
select MFD_CORE
|
||||
help
|
||||
Support for Toshiba Mobile IO Controller TC6393XB
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Multimedia Capabilities Port drivers"
|
||||
|
|
|
@ -8,6 +8,10 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o
|
|||
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
|
||||
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
|
||||
|
||||
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o
|
||||
|
||||
obj-$(CONFIG_MFD_CORE) += mfd-core.o
|
||||
|
||||
obj-$(CONFIG_MCP) += mcp-core.o
|
||||
obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
|
||||
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
|
||||
|
|
114
drivers/mfd/mfd-core.c
Normal file
114
drivers/mfd/mfd-core.c
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* drivers/mfd/mfd-core.c
|
||||
*
|
||||
* core MFD support
|
||||
* Copyright (c) 2006 Ian Molton
|
||||
* Copyright (c) 2007,2008 Dmitry Baryshkov
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/core.h>
|
||||
|
||||
static int mfd_add_device(struct platform_device *parent,
|
||||
const struct mfd_cell *cell,
|
||||
struct resource *mem_base,
|
||||
int irq_base)
|
||||
{
|
||||
struct resource res[cell->num_resources];
|
||||
struct platform_device *pdev;
|
||||
int ret = -ENOMEM;
|
||||
int r;
|
||||
|
||||
pdev = platform_device_alloc(cell->name, parent->id);
|
||||
if (!pdev)
|
||||
goto fail_alloc;
|
||||
|
||||
pdev->dev.parent = &parent->dev;
|
||||
|
||||
ret = platform_device_add_data(pdev,
|
||||
cell, sizeof(struct mfd_cell));
|
||||
if (ret)
|
||||
goto fail_device;
|
||||
|
||||
memzero(res, sizeof(res));
|
||||
for (r = 0; r < cell->num_resources; r++) {
|
||||
res[r].name = cell->resources[r].name;
|
||||
res[r].flags = cell->resources[r].flags;
|
||||
|
||||
/* Find out base to use */
|
||||
if (cell->resources[r].flags & IORESOURCE_MEM) {
|
||||
res[r].parent = mem_base;
|
||||
res[r].start = mem_base->start +
|
||||
cell->resources[r].start;
|
||||
res[r].end = mem_base->start +
|
||||
cell->resources[r].end;
|
||||
} else if (cell->resources[r].flags & IORESOURCE_IRQ) {
|
||||
res[r].start = irq_base +
|
||||
cell->resources[r].start;
|
||||
res[r].end = irq_base +
|
||||
cell->resources[r].end;
|
||||
} else {
|
||||
res[r].parent = cell->resources[r].parent;
|
||||
res[r].start = cell->resources[r].start;
|
||||
res[r].end = cell->resources[r].end;
|
||||
}
|
||||
}
|
||||
|
||||
platform_device_add_resources(pdev, res, cell->num_resources);
|
||||
|
||||
ret = platform_device_add(pdev);
|
||||
if (ret)
|
||||
goto fail_device;
|
||||
|
||||
return 0;
|
||||
|
||||
/* platform_device_del(pdev); */
|
||||
fail_device:
|
||||
platform_device_put(pdev);
|
||||
fail_alloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mfd_add_devices(
|
||||
struct platform_device *parent,
|
||||
const struct mfd_cell *cells, int n_devs,
|
||||
struct resource *mem_base,
|
||||
int irq_base)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < n_devs; i++) {
|
||||
ret = mfd_add_device(parent, cells + i, mem_base, irq_base);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
mfd_remove_devices(parent);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mfd_add_devices);
|
||||
|
||||
static int mfd_remove_devices_fn(struct device *dev, void *unused)
|
||||
{
|
||||
platform_device_unregister(
|
||||
container_of(dev, struct platform_device, dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mfd_remove_devices(struct platform_device *parent)
|
||||
{
|
||||
device_for_each_child(&parent->dev, NULL, mfd_remove_devices_fn);
|
||||
}
|
||||
EXPORT_SYMBOL(mfd_remove_devices);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
|
600
drivers/mfd/tc6393xb.c
Normal file
600
drivers/mfd/tc6393xb.c
Normal file
|
@ -0,0 +1,600 @@
|
|||
/*
|
||||
* Toshiba TC6393XB SoC support
|
||||
*
|
||||
* Copyright(c) 2005-2006 Chris Humbert
|
||||
* Copyright(c) 2005 Dirk Opfer
|
||||
* Copyright(c) 2005 Ian Molton <spyro@f2s.com>
|
||||
* Copyright(c) 2007 Dmitry Baryshkov
|
||||
*
|
||||
* Based on code written by Sharp/Lineo for 2.4 kernels
|
||||
* Based on locomo.c
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tmio.h>
|
||||
#include <linux/mfd/tc6393xb.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#define SCR_REVID 0x08 /* b Revision ID */
|
||||
#define SCR_ISR 0x50 /* b Interrupt Status */
|
||||
#define SCR_IMR 0x52 /* b Interrupt Mask */
|
||||
#define SCR_IRR 0x54 /* b Interrupt Routing */
|
||||
#define SCR_GPER 0x60 /* w GP Enable */
|
||||
#define SCR_GPI_SR(i) (0x64 + (i)) /* b3 GPI Status */
|
||||
#define SCR_GPI_IMR(i) (0x68 + (i)) /* b3 GPI INT Mask */
|
||||
#define SCR_GPI_EDER(i) (0x6c + (i)) /* b3 GPI Edge Detect Enable */
|
||||
#define SCR_GPI_LIR(i) (0x70 + (i)) /* b3 GPI Level Invert */
|
||||
#define SCR_GPO_DSR(i) (0x78 + (i)) /* b3 GPO Data Set */
|
||||
#define SCR_GPO_DOECR(i) (0x7c + (i)) /* b3 GPO Data OE Control */
|
||||
#define SCR_GP_IARCR(i) (0x80 + (i)) /* b3 GP Internal Active Register Control */
|
||||
#define SCR_GP_IARLCR(i) (0x84 + (i)) /* b3 GP INTERNAL Active Register Level Control */
|
||||
#define SCR_GPI_BCR(i) (0x88 + (i)) /* b3 GPI Buffer Control */
|
||||
#define SCR_GPA_IARCR 0x8c /* w GPa Internal Active Register Control */
|
||||
#define SCR_GPA_IARLCR 0x90 /* w GPa Internal Active Register Level Control */
|
||||
#define SCR_GPA_BCR 0x94 /* w GPa Buffer Control */
|
||||
#define SCR_CCR 0x98 /* w Clock Control */
|
||||
#define SCR_PLL2CR 0x9a /* w PLL2 Control */
|
||||
#define SCR_PLL1CR 0x9c /* l PLL1 Control */
|
||||
#define SCR_DIARCR 0xa0 /* b Device Internal Active Register Control */
|
||||
#define SCR_DBOCR 0xa1 /* b Device Buffer Off Control */
|
||||
#define SCR_FER 0xe0 /* b Function Enable */
|
||||
#define SCR_MCR 0xe4 /* w Mode Control */
|
||||
#define SCR_CONFIG 0xfc /* b Configuration Control */
|
||||
#define SCR_DEBUG 0xff /* b Debug */
|
||||
|
||||
#define SCR_CCR_CK32K BIT(0)
|
||||
#define SCR_CCR_USBCK BIT(1)
|
||||
#define SCR_CCR_UNK1 BIT(4)
|
||||
#define SCR_CCR_MCLK_MASK (7 << 8)
|
||||
#define SCR_CCR_MCLK_OFF (0 << 8)
|
||||
#define SCR_CCR_MCLK_12 (1 << 8)
|
||||
#define SCR_CCR_MCLK_24 (2 << 8)
|
||||
#define SCR_CCR_MCLK_48 (3 << 8)
|
||||
#define SCR_CCR_HCLK_MASK (3 << 12)
|
||||
#define SCR_CCR_HCLK_24 (0 << 12)
|
||||
#define SCR_CCR_HCLK_48 (1 << 12)
|
||||
|
||||
#define SCR_FER_USBEN BIT(0) /* USB host enable */
|
||||
#define SCR_FER_LCDCVEN BIT(1) /* polysilicon TFT enable */
|
||||
#define SCR_FER_SLCDEN BIT(2) /* SLCD enable */
|
||||
|
||||
#define SCR_MCR_RDY_MASK (3 << 0)
|
||||
#define SCR_MCR_RDY_OPENDRAIN (0 << 0)
|
||||
#define SCR_MCR_RDY_TRISTATE (1 << 0)
|
||||
#define SCR_MCR_RDY_PUSHPULL (2 << 0)
|
||||
#define SCR_MCR_RDY_UNK BIT(2)
|
||||
#define SCR_MCR_RDY_EN BIT(3)
|
||||
#define SCR_MCR_INT_MASK (3 << 4)
|
||||
#define SCR_MCR_INT_OPENDRAIN (0 << 4)
|
||||
#define SCR_MCR_INT_TRISTATE (1 << 4)
|
||||
#define SCR_MCR_INT_PUSHPULL (2 << 4)
|
||||
#define SCR_MCR_INT_UNK BIT(6)
|
||||
#define SCR_MCR_INT_EN BIT(7)
|
||||
/* bits 8 - 16 are unknown */
|
||||
|
||||
#define TC_GPIO_BIT(i) (1 << (i & 0x7))
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
struct tc6393xb {
|
||||
void __iomem *scr;
|
||||
|
||||
struct gpio_chip gpio;
|
||||
|
||||
struct clk *clk; /* 3,6 Mhz */
|
||||
|
||||
spinlock_t lock; /* protects RMW cycles */
|
||||
|
||||
struct {
|
||||
u8 fer;
|
||||
u16 ccr;
|
||||
u8 gpi_bcr[3];
|
||||
u8 gpo_dsr[3];
|
||||
u8 gpo_doecr[3];
|
||||
} suspend_state;
|
||||
|
||||
struct resource rscr;
|
||||
struct resource *iomem;
|
||||
int irq;
|
||||
int irq_base;
|
||||
};
|
||||
|
||||
enum {
|
||||
TC6393XB_CELL_NAND,
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int tc6393xb_nand_enable(struct platform_device *nand)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(nand->dev.parent);
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
/* SMD buffer on */
|
||||
dev_dbg(&dev->dev, "SMD buffer on\n");
|
||||
iowrite8(0xff, tc6393xb->scr + SCR_GPI_BCR(1));
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource __devinitdata tc6393xb_nand_resources[] = {
|
||||
{
|
||||
.name = TMIO_NAND_CONFIG,
|
||||
.start = 0x0100,
|
||||
.end = 0x01ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = TMIO_NAND_CONTROL,
|
||||
.start = 0x1000,
|
||||
.end = 0x1007,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = TMIO_NAND_IRQ,
|
||||
.start = IRQ_TC6393_NAND,
|
||||
.end = IRQ_TC6393_NAND,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell __devinitdata tc6393xb_cells[] = {
|
||||
[TC6393XB_CELL_NAND] = {
|
||||
.name = "tmio-nand",
|
||||
.enable = tc6393xb_nand_enable,
|
||||
.num_resources = ARRAY_SIZE(tc6393xb_nand_resources),
|
||||
.resources = tc6393xb_nand_resources,
|
||||
},
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int tc6393xb_gpio_get(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
|
||||
|
||||
/* XXX: does dsr also represent inputs? */
|
||||
return ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8))
|
||||
& TC_GPIO_BIT(offset);
|
||||
}
|
||||
|
||||
static void __tc6393xb_gpio_set(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
|
||||
u8 dsr;
|
||||
|
||||
dsr = ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8));
|
||||
if (value)
|
||||
dsr |= TC_GPIO_BIT(offset);
|
||||
else
|
||||
dsr &= ~TC_GPIO_BIT(offset);
|
||||
|
||||
iowrite8(dsr, tc6393xb->scr + SCR_GPO_DSR(offset / 8));
|
||||
}
|
||||
|
||||
static void tc6393xb_gpio_set(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
__tc6393xb_gpio_set(chip, offset, value);
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
}
|
||||
|
||||
static int tc6393xb_gpio_direction_input(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
|
||||
unsigned long flags;
|
||||
u8 doecr;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
doecr = ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
|
||||
doecr &= ~TC_GPIO_BIT(offset);
|
||||
iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc6393xb_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
|
||||
unsigned long flags;
|
||||
u8 doecr;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
__tc6393xb_gpio_set(chip, offset, value);
|
||||
|
||||
doecr = ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
|
||||
doecr |= TC_GPIO_BIT(offset);
|
||||
iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
|
||||
{
|
||||
tc6393xb->gpio.label = "tc6393xb";
|
||||
tc6393xb->gpio.base = gpio_base;
|
||||
tc6393xb->gpio.ngpio = 16;
|
||||
tc6393xb->gpio.set = tc6393xb_gpio_set;
|
||||
tc6393xb->gpio.get = tc6393xb_gpio_get;
|
||||
tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input;
|
||||
tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output;
|
||||
|
||||
return gpiochip_add(&tc6393xb->gpio);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = get_irq_data(irq);
|
||||
unsigned int isr;
|
||||
unsigned int i, irq_base;
|
||||
|
||||
irq_base = tc6393xb->irq_base;
|
||||
|
||||
while ((isr = ioread8(tc6393xb->scr + SCR_ISR) &
|
||||
~ioread8(tc6393xb->scr + SCR_IMR)))
|
||||
for (i = 0; i < TC6393XB_NR_IRQS; i++) {
|
||||
if (isr & (1 << i))
|
||||
generic_handle_irq(irq_base + i);
|
||||
}
|
||||
}
|
||||
|
||||
static void tc6393xb_irq_ack(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static void tc6393xb_irq_mask(unsigned int irq)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
|
||||
unsigned long flags;
|
||||
u8 imr;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
imr = ioread8(tc6393xb->scr + SCR_IMR);
|
||||
imr |= 1 << (irq - tc6393xb->irq_base);
|
||||
iowrite8(imr, tc6393xb->scr + SCR_IMR);
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
}
|
||||
|
||||
static void tc6393xb_irq_unmask(unsigned int irq)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
|
||||
unsigned long flags;
|
||||
u8 imr;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
imr = ioread8(tc6393xb->scr + SCR_IMR);
|
||||
imr &= ~(1 << (irq - tc6393xb->irq_base));
|
||||
iowrite8(imr, tc6393xb->scr + SCR_IMR);
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
}
|
||||
|
||||
static struct irq_chip tc6393xb_chip = {
|
||||
.name = "tc6393xb",
|
||||
.ack = tc6393xb_irq_ack,
|
||||
.mask = tc6393xb_irq_mask,
|
||||
.unmask = tc6393xb_irq_unmask,
|
||||
};
|
||||
|
||||
static void tc6393xb_attach_irq(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
unsigned int irq, irq_base;
|
||||
|
||||
irq_base = tc6393xb->irq_base;
|
||||
|
||||
for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
|
||||
set_irq_chip(irq, &tc6393xb_chip);
|
||||
set_irq_chip_data(irq, tc6393xb);
|
||||
set_irq_handler(irq, handle_edge_irq);
|
||||
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
||||
}
|
||||
|
||||
set_irq_type(tc6393xb->irq, IRQT_FALLING);
|
||||
set_irq_data(tc6393xb->irq, tc6393xb);
|
||||
set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq);
|
||||
}
|
||||
|
||||
static void tc6393xb_detach_irq(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
unsigned int irq, irq_base;
|
||||
|
||||
set_irq_chained_handler(tc6393xb->irq, NULL);
|
||||
set_irq_data(tc6393xb->irq, NULL);
|
||||
|
||||
irq_base = tc6393xb->irq_base;
|
||||
|
||||
for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
|
||||
set_irq_flags(irq, 0);
|
||||
set_irq_chip(irq, NULL);
|
||||
set_irq_chip_data(irq, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int tc6393xb_hw_init(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
iowrite8(tc6393xb->suspend_state.fer, tc6393xb->scr + SCR_FER);
|
||||
iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
|
||||
iowrite16(tc6393xb->suspend_state.ccr, tc6393xb->scr + SCR_CCR);
|
||||
iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
|
||||
SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
|
||||
BIT(15), tc6393xb->scr + SCR_MCR);
|
||||
iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
|
||||
iowrite8(0, tc6393xb->scr + SCR_IRR);
|
||||
iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
|
||||
tc6393xb->scr + SCR_GPO_DSR(i));
|
||||
iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
|
||||
tc6393xb->scr + SCR_GPO_DOECR(i));
|
||||
iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
|
||||
tc6393xb->scr + SCR_GPI_BCR(i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit tc6393xb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb *tc6393xb;
|
||||
struct resource *iomem;
|
||||
struct resource *rscr;
|
||||
int retval, temp;
|
||||
int i;
|
||||
|
||||
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
if (!iomem)
|
||||
return -EINVAL;
|
||||
|
||||
tc6393xb = kzalloc(sizeof *tc6393xb, GFP_KERNEL);
|
||||
if (!tc6393xb) {
|
||||
retval = -ENOMEM;
|
||||
goto err_kzalloc;
|
||||
}
|
||||
|
||||
spin_lock_init(&tc6393xb->lock);
|
||||
|
||||
platform_set_drvdata(dev, tc6393xb);
|
||||
tc6393xb->iomem = iomem;
|
||||
tc6393xb->irq = platform_get_irq(dev, 0);
|
||||
tc6393xb->irq_base = tcpd->irq_base;
|
||||
|
||||
tc6393xb->clk = clk_get(&dev->dev, "GPIO27_CLK" /* "CK3P6MI" */);
|
||||
if (IS_ERR(tc6393xb->clk)) {
|
||||
retval = PTR_ERR(tc6393xb->clk);
|
||||
goto err_clk_get;
|
||||
}
|
||||
|
||||
rscr = &tc6393xb->rscr;
|
||||
rscr->name = "tc6393xb-core";
|
||||
rscr->start = iomem->start;
|
||||
rscr->end = iomem->start + 0xff;
|
||||
rscr->flags = IORESOURCE_MEM;
|
||||
|
||||
retval = request_resource(iomem, rscr);
|
||||
if (retval)
|
||||
goto err_request_scr;
|
||||
|
||||
tc6393xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
|
||||
if (!tc6393xb->scr) {
|
||||
retval = -ENOMEM;
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
retval = clk_enable(tc6393xb->clk);
|
||||
if (retval)
|
||||
goto err_clk_enable;
|
||||
|
||||
retval = tcpd->enable(dev);
|
||||
if (retval)
|
||||
goto err_enable;
|
||||
|
||||
tc6393xb->suspend_state.fer = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
tc6393xb->suspend_state.gpo_dsr[i] =
|
||||
(tcpd->scr_gpo_dsr >> (8 * i)) & 0xff;
|
||||
tc6393xb->suspend_state.gpo_doecr[i] =
|
||||
(tcpd->scr_gpo_doecr >> (8 * i)) & 0xff;
|
||||
}
|
||||
/*
|
||||
* It may be necessary to change this back to
|
||||
* platform-dependant code
|
||||
*/
|
||||
tc6393xb->suspend_state.ccr = SCR_CCR_UNK1 |
|
||||
SCR_CCR_HCLK_48;
|
||||
|
||||
retval = tc6393xb_hw_init(dev);
|
||||
if (retval)
|
||||
goto err_hw_init;
|
||||
|
||||
printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n",
|
||||
ioread8(tc6393xb->scr + SCR_REVID),
|
||||
(unsigned long) iomem->start, tc6393xb->irq);
|
||||
|
||||
tc6393xb->gpio.base = -1;
|
||||
|
||||
if (tcpd->gpio_base >= 0) {
|
||||
retval = tc6393xb_register_gpio(tc6393xb, tcpd->gpio_base);
|
||||
if (retval)
|
||||
goto err_gpio_add;
|
||||
}
|
||||
|
||||
if (tc6393xb->irq)
|
||||
tc6393xb_attach_irq(dev);
|
||||
|
||||
tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
|
||||
|
||||
retval = mfd_add_devices(dev,
|
||||
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
|
||||
iomem, tcpd->irq_base);
|
||||
|
||||
return 0;
|
||||
|
||||
if (tc6393xb->irq)
|
||||
tc6393xb_detach_irq(dev);
|
||||
|
||||
err_gpio_add:
|
||||
if (tc6393xb->gpio.base != -1)
|
||||
temp = gpiochip_remove(&tc6393xb->gpio);
|
||||
err_hw_init:
|
||||
tcpd->disable(dev);
|
||||
err_clk_enable:
|
||||
clk_disable(tc6393xb->clk);
|
||||
err_enable:
|
||||
iounmap(tc6393xb->scr);
|
||||
err_ioremap:
|
||||
release_resource(&tc6393xb->rscr);
|
||||
err_request_scr:
|
||||
clk_put(tc6393xb->clk);
|
||||
err_clk_get:
|
||||
kfree(tc6393xb);
|
||||
err_kzalloc:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int __devexit tc6393xb_remove(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
mfd_remove_devices(dev);
|
||||
|
||||
if (tc6393xb->irq)
|
||||
tc6393xb_detach_irq(dev);
|
||||
|
||||
if (tc6393xb->gpio.base != -1) {
|
||||
ret = gpiochip_remove(&tc6393xb->gpio);
|
||||
if (ret) {
|
||||
dev_err(&dev->dev, "Can't remove gpio chip: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = tcpd->disable(dev);
|
||||
|
||||
clk_disable(tc6393xb->clk);
|
||||
|
||||
iounmap(tc6393xb->scr);
|
||||
|
||||
release_resource(&tc6393xb->rscr);
|
||||
|
||||
platform_set_drvdata(dev, NULL);
|
||||
|
||||
clk_put(tc6393xb->clk);
|
||||
|
||||
kfree(tc6393xb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
|
||||
tc6393xb->suspend_state.ccr = ioread16(tc6393xb->scr + SCR_CCR);
|
||||
tc6393xb->suspend_state.fer = ioread8(tc6393xb->scr + SCR_FER);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
tc6393xb->suspend_state.gpo_dsr[i] =
|
||||
ioread8(tc6393xb->scr + SCR_GPO_DSR(i));
|
||||
tc6393xb->suspend_state.gpo_doecr[i] =
|
||||
ioread8(tc6393xb->scr + SCR_GPO_DOECR(i));
|
||||
tc6393xb->suspend_state.gpi_bcr[i] =
|
||||
ioread8(tc6393xb->scr + SCR_GPI_BCR(i));
|
||||
}
|
||||
|
||||
return tcpd->suspend(dev);
|
||||
}
|
||||
|
||||
static int tc6393xb_resume(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
int ret = tcpd->resume(dev);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return tc6393xb_hw_init(dev);
|
||||
}
|
||||
#else
|
||||
#define tc6393xb_suspend NULL
|
||||
#define tc6393xb_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver tc6393xb_driver = {
|
||||
.probe = tc6393xb_probe,
|
||||
.remove = __devexit_p(tc6393xb_remove),
|
||||
.suspend = tc6393xb_suspend,
|
||||
.resume = tc6393xb_resume,
|
||||
|
||||
.driver = {
|
||||
.name = "tc6393xb",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tc6393xb_init(void)
|
||||
{
|
||||
return platform_driver_register(&tc6393xb_driver);
|
||||
}
|
||||
|
||||
static void __exit tc6393xb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tc6393xb_driver);
|
||||
}
|
||||
|
||||
subsys_initcall(tc6393xb_init);
|
||||
module_exit(tc6393xb_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer");
|
||||
MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller");
|
||||
MODULE_ALIAS("platform:tc6393xb");
|
|
@ -208,6 +208,11 @@ extern void pxa_gpio_set_value(unsigned gpio, int value);
|
|||
*/
|
||||
extern unsigned int get_memclk_frequency_10khz(void);
|
||||
|
||||
/*
|
||||
* register GPIO as reset generator
|
||||
*/
|
||||
extern int init_gpio_reset(int gpio);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
|
||||
|
|
|
@ -180,6 +180,7 @@
|
|||
#define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1)
|
||||
#elif defined(CONFIG_ARCH_LUBBOCK) || \
|
||||
defined(CONFIG_MACH_LOGICPD_PXA270) || \
|
||||
defined(CONFIG_MACH_TOSA) || \
|
||||
defined(CONFIG_MACH_MAINSTONE) || \
|
||||
defined(CONFIG_MACH_PCM027) || \
|
||||
defined(CONFIG_MACH_MAGICIAN)
|
||||
|
|
|
@ -21,19 +21,4 @@ static inline void arch_idle(void)
|
|||
}
|
||||
|
||||
|
||||
static inline void arch_reset(char mode)
|
||||
{
|
||||
if (cpu_is_pxa2xx())
|
||||
RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
|
||||
|
||||
if (mode == 's') {
|
||||
/* Jump into ROM at address 0 */
|
||||
cpu_reset(0);
|
||||
} else {
|
||||
/* Initialize the watchdog and let it fire */
|
||||
OWER = OWER_WME;
|
||||
OSSR = OSSR_M3;
|
||||
OSMR3 = OSCR + 368640; /* ... in 100 ms */
|
||||
}
|
||||
}
|
||||
|
||||
void arch_reset(char mode);
|
||||
|
|
|
@ -25,21 +25,18 @@
|
|||
*/
|
||||
#define TOSA_SCOOP_GPIO_BASE NR_BUILTIN_GPIO
|
||||
#define TOSA_SCOOP_PXA_VCORE1 SCOOP_GPCR_PA11
|
||||
#define TOSA_SCOOP_TC6393_REST_IN SCOOP_GPCR_PA12
|
||||
#define TOSA_GPIO_TC6393XB_REST_IN (TOSA_SCOOP_GPIO_BASE + 1)
|
||||
#define TOSA_GPIO_IR_POWERDWN (TOSA_SCOOP_GPIO_BASE + 2)
|
||||
#define TOSA_GPIO_SD_WP (TOSA_SCOOP_GPIO_BASE + 3)
|
||||
#define TOSA_GPIO_PWR_ON (TOSA_SCOOP_GPIO_BASE + 4)
|
||||
#define TOSA_SCOOP_AUD_PWR_ON SCOOP_GPCR_PA16
|
||||
#define TOSA_SCOOP_BT_RESET SCOOP_GPCR_PA17
|
||||
#define TOSA_SCOOP_BT_PWR_EN SCOOP_GPCR_PA18
|
||||
#define TOSA_GPIO_BT_RESET (TOSA_SCOOP_GPIO_BASE + 6)
|
||||
#define TOSA_GPIO_BT_PWR_EN (TOSA_SCOOP_GPIO_BASE + 7)
|
||||
#define TOSA_SCOOP_AC_IN_OL SCOOP_GPCR_PA19
|
||||
|
||||
/* GPIO Direction 1 : output mode / 0:input mode */
|
||||
#define TOSA_SCOOP_IO_DIR ( TOSA_SCOOP_PXA_VCORE1 | TOSA_SCOOP_TC6393_REST_IN | \
|
||||
TOSA_SCOOP_AUD_PWR_ON |\
|
||||
TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN )
|
||||
/* GPIO out put level when init 1: Hi */
|
||||
#define TOSA_SCOOP_IO_OUT ( TOSA_SCOOP_TC6393_REST_IN )
|
||||
#define TOSA_SCOOP_IO_DIR (TOSA_SCOOP_PXA_VCORE1 | \
|
||||
TOSA_SCOOP_AUD_PWR_ON)
|
||||
|
||||
/*
|
||||
* SCOOP2 jacket GPIOs
|
||||
|
@ -49,16 +46,34 @@
|
|||
#define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1)
|
||||
#define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2)
|
||||
#define TOSA_GPIO_USB_PULLUP (TOSA_SCOOP_JC_GPIO_BASE + 3)
|
||||
#define TOSA_SCOOP_JC_TC6393_SUSPEND SCOOP_GPCR_PA15
|
||||
#define TOSA_SCOOP_JC_TC3693_L3V_ON SCOOP_GPCR_PA16
|
||||
#define TOSA_GPIO_TC6393XB_SUSPEND (TOSA_SCOOP_JC_GPIO_BASE + 4)
|
||||
#define TOSA_GPIO_TC6393XB_L3V_ON (TOSA_SCOOP_JC_GPIO_BASE + 5)
|
||||
#define TOSA_SCOOP_JC_WLAN_DETECT SCOOP_GPCR_PA17
|
||||
#define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7)
|
||||
#define TOSA_SCOOP_JC_CARD_LIMIT_SEL SCOOP_GPCR_PA19
|
||||
|
||||
/* GPIO Direction 1 : output mode / 0:input mode */
|
||||
#define TOSA_SCOOP_JC_IO_DIR ( \
|
||||
TOSA_SCOOP_JC_TC6393_SUSPEND | TOSA_SCOOP_JC_TC3693_L3V_ON | \
|
||||
TOSA_SCOOP_JC_CARD_LIMIT_SEL )
|
||||
#define TOSA_SCOOP_JC_IO_DIR (TOSA_SCOOP_JC_CARD_LIMIT_SEL)
|
||||
|
||||
/*
|
||||
* TC6393XB GPIOs
|
||||
*/
|
||||
#define TOSA_TC6393XB_GPIO_BASE (NR_BUILTIN_GPIO + 2 * 12)
|
||||
#define TOSA_TC6393XB_GPIO(i) (TOSA_TC6393XB_GPIO_BASE + (i))
|
||||
#define TOSA_TC6393XB_GPIO_BIT(gpio) (1 << (gpio - TOSA_TC6393XB_GPIO_BASE))
|
||||
|
||||
#define TOSA_GPIO_TG_ON (TOSA_TC6393XB_GPIO_BASE + 0)
|
||||
#define TOSA_GPIO_L_MUTE (TOSA_TC6393XB_GPIO_BASE + 1)
|
||||
#define TOSA_GPIO_BL_C20MA (TOSA_TC6393XB_GPIO_BASE + 3)
|
||||
#define TOSA_GPIO_CARD_VCC_ON (TOSA_TC6393XB_GPIO_BASE + 4)
|
||||
#define TOSA_GPIO_CHARGE_OFF (TOSA_TC6393XB_GPIO_BASE + 6)
|
||||
#define TOSA_GPIO_CHARGE_OFF_JC (TOSA_TC6393XB_GPIO_BASE + 7)
|
||||
#define TOSA_GPIO_BAT0_V_ON (TOSA_TC6393XB_GPIO_BASE + 9)
|
||||
#define TOSA_GPIO_BAT1_V_ON (TOSA_TC6393XB_GPIO_BASE + 10)
|
||||
#define TOSA_GPIO_BU_CHRG_ON (TOSA_TC6393XB_GPIO_BASE + 11)
|
||||
#define TOSA_GPIO_BAT_SW_ON (TOSA_TC6393XB_GPIO_BASE + 12)
|
||||
#define TOSA_GPIO_BAT0_TH_ON (TOSA_TC6393XB_GPIO_BASE + 14)
|
||||
#define TOSA_GPIO_BAT1_TH_ON (TOSA_TC6393XB_GPIO_BASE + 15)
|
||||
|
||||
/*
|
||||
* Timing Generator
|
||||
|
@ -84,13 +99,13 @@
|
|||
#define TOSA_GPIO_JACKET_DETECT (7)
|
||||
#define TOSA_GPIO_nSD_DETECT (9)
|
||||
#define TOSA_GPIO_nSD_INT (10)
|
||||
#define TOSA_GPIO_TC6393_CLK (11)
|
||||
#define TOSA_GPIO_TC6393XB_CLK (11)
|
||||
#define TOSA_GPIO_BAT1_CRG (12)
|
||||
#define TOSA_GPIO_CF_CD (13)
|
||||
#define TOSA_GPIO_BAT0_CRG (14)
|
||||
#define TOSA_GPIO_TC6393_INT (15)
|
||||
#define TOSA_GPIO_TC6393XB_INT (15)
|
||||
#define TOSA_GPIO_BAT0_LOW (17)
|
||||
#define TOSA_GPIO_TC6393_RDY (18)
|
||||
#define TOSA_GPIO_TC6393XB_RDY (18)
|
||||
#define TOSA_GPIO_ON_RESET (19)
|
||||
#define TOSA_GPIO_EAR_IN (20)
|
||||
#define TOSA_GPIO_CF_IRQ (21) /* CF slot0 Ready */
|
||||
|
@ -99,6 +114,7 @@
|
|||
#define TOSA_GPIO_TP_INT (32) /* Touch Panel pen down interrupt */
|
||||
#define TOSA_GPIO_JC_CF_IRQ (36) /* CF slot1 Ready */
|
||||
#define TOSA_GPIO_BAT_LOCKED (38) /* Battery locked */
|
||||
#define TOSA_GPIO_IRDA_TX (47)
|
||||
#define TOSA_GPIO_TG_SPI_SCLK (81)
|
||||
#define TOSA_GPIO_TG_SPI_CS (82)
|
||||
#define TOSA_GPIO_TG_SPI_MOSI (83)
|
||||
|
@ -137,7 +153,7 @@
|
|||
#define TOSA_IRQ_GPIO_BAT1_CRG IRQ_GPIO(TOSA_GPIO_BAT1_CRG)
|
||||
#define TOSA_IRQ_GPIO_CF_CD IRQ_GPIO(TOSA_GPIO_CF_CD)
|
||||
#define TOSA_IRQ_GPIO_BAT0_CRG IRQ_GPIO(TOSA_GPIO_BAT0_CRG)
|
||||
#define TOSA_IRQ_GPIO_TC6393_INT IRQ_GPIO(TOSA_GPIO_TC6393_INT)
|
||||
#define TOSA_IRQ_GPIO_TC6393XB_INT IRQ_GPIO(TOSA_GPIO_TC6393XB_INT)
|
||||
#define TOSA_IRQ_GPIO_BAT0_LOW IRQ_GPIO(TOSA_GPIO_BAT0_LOW)
|
||||
#define TOSA_IRQ_GPIO_EAR_IN IRQ_GPIO(TOSA_GPIO_EAR_IN)
|
||||
#define TOSA_IRQ_GPIO_CF_IRQ IRQ_GPIO(TOSA_GPIO_CF_IRQ)
|
||||
|
|
22
include/asm-arm/arch-pxa/tosa_bt.h
Normal file
22
include/asm-arm/arch-pxa/tosa_bt.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Tosa bluetooth built-in chip control.
|
||||
*
|
||||
* Later it may be shared with some other platforms.
|
||||
*
|
||||
* Copyright (c) 2008 Dmitry Baryshkov
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef TOSA_BT_H
|
||||
#define TOSA_BT_H
|
||||
|
||||
struct tosa_bt_data {
|
||||
int gpio_pwr;
|
||||
int gpio_reset;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
55
include/linux/mfd/core.h
Normal file
55
include/linux/mfd/core.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef MFD_CORE_H
|
||||
#define MFD_CORE_H
|
||||
/*
|
||||
* drivers/mfd/mfd-core.h
|
||||
*
|
||||
* core MFD support
|
||||
* Copyright (c) 2006 Ian Molton
|
||||
* Copyright (c) 2007 Dmitry Baryshkov
|
||||
*
|
||||
* 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/platform_device.h>
|
||||
|
||||
/*
|
||||
* This struct describes the MFD part ("cell").
|
||||
* After registration the copy of this structure will become the platform data
|
||||
* of the resulting platform_device
|
||||
*/
|
||||
struct mfd_cell {
|
||||
const char *name;
|
||||
|
||||
int (*enable)(struct platform_device *dev);
|
||||
int (*disable)(struct platform_device *dev);
|
||||
int (*suspend)(struct platform_device *dev);
|
||||
int (*resume)(struct platform_device *dev);
|
||||
|
||||
void *driver_data; /* driver-specific data */
|
||||
|
||||
/*
|
||||
* This resources can be specified relatievly to the parent device.
|
||||
* For accessing device you should use resources from device
|
||||
*/
|
||||
int num_resources;
|
||||
const struct resource *resources;
|
||||
};
|
||||
|
||||
static inline struct mfd_cell *
|
||||
mfd_get_cell(struct platform_device *pdev)
|
||||
{
|
||||
return (struct mfd_cell *)pdev->dev.platform_data;
|
||||
}
|
||||
|
||||
extern int mfd_add_devices(
|
||||
struct platform_device *parent,
|
||||
const struct mfd_cell *cells, int n_devs,
|
||||
struct resource *mem_base,
|
||||
int irq_base);
|
||||
|
||||
extern void mfd_remove_devices(struct platform_device *parent);
|
||||
|
||||
#endif
|
49
include/linux/mfd/tc6393xb.h
Normal file
49
include/linux/mfd/tc6393xb.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Toshiba TC6393XB SoC support
|
||||
*
|
||||
* Copyright(c) 2005-2006 Chris Humbert
|
||||
* Copyright(c) 2005 Dirk Opfer
|
||||
* Copyright(c) 2005 Ian Molton <spyro@f2s.com>
|
||||
* Copyright(c) 2007 Dmitry Baryshkov
|
||||
*
|
||||
* Based on code written by Sharp/Lineo for 2.4 kernels
|
||||
* Based on locomo.c
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TC6393XB_H
|
||||
#define TC6393XB_H
|
||||
|
||||
/* Also one should provide the CK3P6MI clock */
|
||||
struct tc6393xb_platform_data {
|
||||
u16 scr_pll2cr; /* PLL2 Control */
|
||||
u16 scr_gper; /* GP Enable */
|
||||
u32 scr_gpo_doecr; /* GPO Data OE Control */
|
||||
u32 scr_gpo_dsr; /* GPO Data Set */
|
||||
|
||||
int (*enable)(struct platform_device *dev);
|
||||
int (*disable)(struct platform_device *dev);
|
||||
int (*suspend)(struct platform_device *dev);
|
||||
int (*resume)(struct platform_device *dev);
|
||||
|
||||
int irq_base; /* a base for cascaded irq */
|
||||
int gpio_base;
|
||||
|
||||
struct tmio_nand_data *nand_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Relative to irq_base
|
||||
*/
|
||||
#define IRQ_TC6393_NAND 0
|
||||
#define IRQ_TC6393_MMC 1
|
||||
#define IRQ_TC6393_OHCI 2
|
||||
#define IRQ_TC6393_SERIAL 3
|
||||
#define IRQ_TC6393_FB 4
|
||||
|
||||
#define TC6393XB_NR_IRQS 8
|
||||
|
||||
#endif
|
17
include/linux/mfd/tmio.h
Normal file
17
include/linux/mfd/tmio.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef MFD_TMIO_H
|
||||
#define MFD_TMIO_H
|
||||
|
||||
/*
|
||||
* data for the NAND controller
|
||||
*/
|
||||
struct tmio_nand_data {
|
||||
struct nand_bbt_descr *badblock_pattern;
|
||||
struct mtd_partition *partition;
|
||||
unsigned int num_partitions;
|
||||
};
|
||||
|
||||
#define TMIO_NAND_CONFIG "tmio-nand-config"
|
||||
#define TMIO_NAND_CONTROL "tmio-nand-control"
|
||||
#define TMIO_NAND_IRQ "tmio-nand"
|
||||
|
||||
#endif
|
|
@ -48,6 +48,7 @@ config SND_PXA2XX_SOC_POODLE
|
|||
config SND_PXA2XX_SOC_TOSA
|
||||
tristate "SoC AC97 Audio support for Tosa"
|
||||
depends on SND_PXA2XX_SOC && MACH_TOSA
|
||||
depends on MFD_TC6393XB
|
||||
select SND_PXA2XX_SOC_AC97
|
||||
select SND_SOC_WM9712
|
||||
help
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@ -31,7 +32,7 @@
|
|||
#include <sound/soc-dapm.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware/tmio.h>
|
||||
#include <asm/arch/tosa.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/audio.h>
|
||||
|
@ -138,10 +139,7 @@ static int tosa_set_spk(struct snd_kcontrol *kcontrol,
|
|||
static int tosa_hp_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *k, int event)
|
||||
{
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
|
||||
else
|
||||
reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
|
||||
gpio_set_value(TOSA_GPIO_L_MUTE, SND_SOC_DAPM_EVENT_ON(event) ? 1 :0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -261,16 +259,28 @@ static int __init tosa_init(void)
|
|||
if (!machine_is_tosa())
|
||||
return -ENODEV;
|
||||
|
||||
ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
|
||||
if (ret)
|
||||
return ret;
|
||||
gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
|
||||
|
||||
tosa_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!tosa_snd_device)
|
||||
return -ENOMEM;
|
||||
if (!tosa_snd_device) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata);
|
||||
tosa_snd_devdata.dev = &tosa_snd_device->dev;
|
||||
ret = platform_device_add(tosa_snd_device);
|
||||
|
||||
if (ret)
|
||||
platform_device_put(tosa_snd_device);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
platform_device_put(tosa_snd_device);
|
||||
|
||||
err_alloc:
|
||||
gpio_free(TOSA_GPIO_L_MUTE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -278,6 +288,7 @@ static int __init tosa_init(void)
|
|||
static void __exit tosa_exit(void)
|
||||
{
|
||||
platform_device_unregister(tosa_snd_device);
|
||||
gpio_free(TOSA_GPIO_L_MUTE);
|
||||
}
|
||||
|
||||
module_init(tosa_init);
|
||||
|
|
Loading…
Reference in New Issue
Block a user