From 364416bb01613f238157cd55dcde82f30b969e28 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 7 Mar 2008 09:54:20 +0000 Subject: linux-rp-2.6.24: Add missing patches from previous commit --- ...me-registration-of-regions-of-memory-that.patch | 201 ++++ ...alloc_coherent-on-ARM-so-that-it-supports.patch | 260 +++++ .../tosa/0003-Core-MFD-support.patch | 243 +++++ .../0004-Add-support-for-tc6393xb-MFD-core.patch | 907 ++++++++++++++++ .../0005-Add-support-for-tc6387xb-MFD-core.patch | 249 +++++ .../0006-Add-support-for-t7l66xb-MFD-core.patch | 653 +++++++++++ ...07-Common-headers-for-TMIO-MFD-subdevices.patch | 81 ++ .../tosa/0008-Nand-driver-for-TMIO-devices.patch | 608 +++++++++++ .../tosa/0009-FB-driver-for-TMIO-devices.patch | 1128 ++++++++++++++++++++ .../tosa/0010-OHCI-driver-for-TMIO-devices.patch | 431 ++++++++ .../tosa/0011-MMC-driver-for-TMIO-devices.patch | 891 ++++++++++++++++ .../tosa/0012-Tosa-keyboard-support.patch | 593 ++++++++++ ...-gadget-pxa2xx_udc-supports-inverted-vbus.patch | 61 ++ .../tosa/0014-tosa_udc_use_gpio_vbus.patch.patch | 38 + .../tosa/0015-sharpsl-export-params.patch | 32 + ...fixes-the-pxa25x-clocks-definitions-to-ad.patch | 44 + .../0017-Convert-pxa2xx-UDC-to-use-debugfs.patch | 280 +++++ ...2xx_udc-to-balance-calls-to-clk_enable-cl.patch | 225 ++++ ...xa-remove-periodic-mode-emulation-support.patch | 128 +++ ...ew-device-clock-backports-from-2.6.24-git.patch | 257 +++++ ...y-drivers-gpio-directory-for-gpiolib-infr.patch | 121 +++ ...-implementation-infrastructure-that-platf.patch | 746 +++++++++++++ ...-gpiolib-support-for-the-PXA-architecture.patch | 498 +++++++++ ...cumentation-gpio.txt-primarily-to-include.patch | 238 +++++ ...f-by-Dmitry-Baryshkov-dbaryshkov-gmail.co.patch | 434 ++++++++ ...nk-we-should-check-for-IRQs-when-determin.patch | 134 +++ ...ne-of-the-most-common-for-small-non-recha.patch | 59 + ...spend-resume-wakeup-support-for-pda_power.patch | 72 ++ ...ing-VOLTAGE_-properties-for-apm-calculati.patch | 163 +++ .../0030-Core-driver-for-WM97xx-touchscreens.patch | 1083 +++++++++++++++++++ ...31-Add-chip-driver-for-WM9705-touchscreen.patch | 383 +++++++ ...32-Add-chip-driver-for-WM9712-touchscreen.patch | 492 +++++++++ ...33-Add-chip-driver-for-WM9713-touchscreen.patch | 490 +++++++++ ...-WM97xx-touchscreens-in-streaming-mode-on.patch | 329 ++++++ ...m-and-MAINTAINERS-entry-for-WM97xx-touchs.patch | 122 +++ .../0036-Set-id-to-1-for-wm97xx-subdevices.patch | 35 + ...the-codec-list-in-snd_soc_dapm_new_widget.patch | 41 + ...the-codec-list-in-snd_soc_dapm_new_widget.patch | 57 + ...Add-generic-framework-for-managing-clocks.patch | 446 ++++++++ .../tosa/0040-Clocklib-debugfs-support.patch | 108 ++ ...e60c2aec59ccf4fca0a7fd20495f82b1d2-Mon-Se.patch | 593 ++++++++++ .../0042-Use-correct-clock-for-IrDA-on-pxa.patch | 26 + .../0043-Use-clocklib-for-sa1100-sub-arch.patch | 153 +++ .../tosa/0044-fix-tmio_mmc-debug-compilation.patch | 26 + .../tosa/0045-Update-tmio_ohci.patch | 416 ++++++++ .../tosa/0046-patch-tc6393xb-cleanup.patch | 66 ++ ...use-bitmasks-instead-of-bit-field-structs.patch | 412 +++++++ .../tosa/0048-tc6393xb-GPIO-support.patch | 225 ++++ .../0049-platform-support-for-TMIO-on-tosa.patch | 373 +++++++ .../tosa/0050-tosa-update-for-tc6393xb-gpio.patch | 99 ++ ...-fix-sound-soc-pxa-tosa.c-to-new-gpio-api.patch | 86 ++ .../0052-tosa-platform-backlight-support.patch | 400 +++++++ .../tosa/0053-sound-soc-codecs-wm9712.c-28.patch | 56 + .../tosa/0054-sound-soc-codecs-wm9712.c-2.patch | 28 + ...WERON-to-the-list-of-devices-that-we-supp.patch | 30 + ...6-Support-resetting-by-asserting-GPIO-pin.patch | 126 +++ .../tosa/0057-Clean-up-tosa-resetting.patch | 70 ++ .../tosa/0058-Fix-tosakbd-suspend.patch | 27 + .../tosa/0059-patch-tosa-wakeup-test.patch | 46 + ...0060-Add-support-for-power_supply-on-tosa.patch | 623 +++++++++++ .../linux-rp-2.6.24/tosa/0061-tosa-bat-unify.patch | 342 ++++++ .../tosa/0062-tosa-bat-fix-charging.patch | 78 ++ .../tosa/0063-patch-tosa-bat-jacket-detect.patch | 84 ++ .../tosa/0064-Export-modes-via-sysfs.patch | 27 + .../tosa/0065-wm97xx-core-fixes.patch | 49 + .../0066-tmiofb_probe-should-be-__devinit.patch | 26 + .../linux-rp-2.6.24/tosa/0067-modeswitching.patch | 225 ++++ .../tosa/0068-Preliminary-tosa-denoiser.patch | 239 +++++ 68 files changed, 18312 insertions(+) create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0001-Allow-runtime-registration-of-regions-of-memory-that.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0002-Modify-dma_alloc_coherent-on-ARM-so-that-it-supports.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0003-Core-MFD-support.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0004-Add-support-for-tc6393xb-MFD-core.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0005-Add-support-for-tc6387xb-MFD-core.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0006-Add-support-for-t7l66xb-MFD-core.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0007-Common-headers-for-TMIO-MFD-subdevices.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0008-Nand-driver-for-TMIO-devices.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0009-FB-driver-for-TMIO-devices.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0010-OHCI-driver-for-TMIO-devices.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0011-MMC-driver-for-TMIO-devices.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0012-Tosa-keyboard-support.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0013-USB-gadget-pxa2xx_udc-supports-inverted-vbus.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0014-tosa_udc_use_gpio_vbus.patch.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0015-sharpsl-export-params.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0016-This-patch-fixes-the-pxa25x-clocks-definitions-to-ad.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0017-Convert-pxa2xx-UDC-to-use-debugfs.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0018-Fix-the-pxa2xx_udc-to-balance-calls-to-clk_enable-cl.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0019-pxa-remove-periodic-mode-emulation-support.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0020-Provide-dew-device-clock-backports-from-2.6.24-git.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0021-Add-an-empty-drivers-gpio-directory-for-gpiolib-infr.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0022-Provide-new-implementation-infrastructure-that-platf.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0023-This-adds-gpiolib-support-for-the-PXA-architecture.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0024-Update-Documentation-gpio.txt-primarily-to-include.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0025-Signed-off-by-Dmitry-Baryshkov-dbaryshkov-gmail.co.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0026-I-don-t-think-we-should-check-for-IRQs-when-determin.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0027-Add-LiMn-one-of-the-most-common-for-small-non-recha.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0028-Add-suspend-resume-wakeup-support-for-pda_power.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0029-Support-using-VOLTAGE_-properties-for-apm-calculati.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0030-Core-driver-for-WM97xx-touchscreens.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0031-Add-chip-driver-for-WM9705-touchscreen.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0032-Add-chip-driver-for-WM9712-touchscreen.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0033-Add-chip-driver-for-WM9713-touchscreen.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0034-Driver-for-WM97xx-touchscreens-in-streaming-mode-on.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0035-Build-system-and-MAINTAINERS-entry-for-WM97xx-touchs.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0036-Set-id-to-1-for-wm97xx-subdevices.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0037-Don-t-lock-the-codec-list-in-snd_soc_dapm_new_widget.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0038-Don-t-lock-the-codec-list-in-snd_soc_dapm_new_widget.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0039-Add-generic-framework-for-managing-clocks.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0040-Clocklib-debugfs-support.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0041-From-80a359e60c2aec59ccf4fca0a7fd20495f82b1d2-Mon-Se.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0042-Use-correct-clock-for-IrDA-on-pxa.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0043-Use-clocklib-for-sa1100-sub-arch.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0044-fix-tmio_mmc-debug-compilation.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0045-Update-tmio_ohci.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0046-patch-tc6393xb-cleanup.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0047-tc6393xb-use-bitmasks-instead-of-bit-field-structs.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0048-tc6393xb-GPIO-support.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0049-platform-support-for-TMIO-on-tosa.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0050-tosa-update-for-tc6393xb-gpio.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0051-fix-sound-soc-pxa-tosa.c-to-new-gpio-api.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0052-tosa-platform-backlight-support.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0053-sound-soc-codecs-wm9712.c-28.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0054-sound-soc-codecs-wm9712.c-2.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0055-Add-GPIO_POWERON-to-the-list-of-devices-that-we-supp.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0056-Support-resetting-by-asserting-GPIO-pin.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0057-Clean-up-tosa-resetting.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0058-Fix-tosakbd-suspend.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0059-patch-tosa-wakeup-test.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0060-Add-support-for-power_supply-on-tosa.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0061-tosa-bat-unify.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0062-tosa-bat-fix-charging.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0063-patch-tosa-bat-jacket-detect.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0064-Export-modes-via-sysfs.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0065-wm97xx-core-fixes.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0066-tmiofb_probe-should-be-__devinit.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0067-modeswitching.patch create mode 100644 packages/linux/linux-rp-2.6.24/tosa/0068-Preliminary-tosa-denoiser.patch (limited to 'packages/linux') diff --git a/packages/linux/linux-rp-2.6.24/tosa/0001-Allow-runtime-registration-of-regions-of-memory-that.patch b/packages/linux/linux-rp-2.6.24/tosa/0001-Allow-runtime-registration-of-regions-of-memory-that.patch new file mode 100644 index 0000000000..ba79b4a470 --- /dev/null +++ b/packages/linux/linux-rp-2.6.24/tosa/0001-Allow-runtime-registration-of-regions-of-memory-that.patch @@ -0,0 +1,201 @@ +From d48a09b301d9a460d5ce027433e8cb8872e7b5c3 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 4 Jan 2008 18:26:38 +0000 +Subject: [PATCH 01/64] Allow runtime registration of regions of memory that require dma bouncing. + +--- + arch/arm/common/Kconfig | 4 ++ + arch/arm/common/dmabounce.c | 82 ++++++++++++++++++++++++++++++++++++- + arch/arm/common/sa1111.c | 2 +- + arch/arm/mach-ixp4xx/Kconfig | 1 + + arch/arm/mach-ixp4xx/common-pci.c | 2 +- + 5 files changed, 87 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig +index 3e07346..5f357fb 100644 +--- a/arch/arm/common/Kconfig ++++ b/arch/arm/common/Kconfig +@@ -13,10 +13,14 @@ config ICST307 + config SA1111 + bool + select DMABOUNCE ++ select PLATFORM_DMABOUNCE + + config DMABOUNCE + bool + ++config PLATFORM_DMABOUNCE ++ bool ++ + config TIMER_ACORN + bool + +diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c +index 52fc6a8..ed80abe 100644 +--- a/arch/arm/common/dmabounce.c ++++ b/arch/arm/common/dmabounce.c +@@ -16,6 +16,7 @@ + * + * Copyright (C) 2002 Hewlett Packard Company. + * Copyright (C) 2004 MontaVista Software, Inc. ++ * 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 +@@ -24,6 +25,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -80,6 +82,80 @@ struct dmabounce_device_info { + rwlock_t lock; + }; + ++struct dmabounce_check_entry { ++ struct list_head list; ++ dmabounce_check checker; ++ void *data; ++}; ++ ++static struct list_head checkers = LIST_HEAD_INIT(checkers); ++static rwlock_t checkers_lock = RW_LOCK_UNLOCKED; ++ ++int ++dmabounce_register_checker(dmabounce_check function, void *data) ++{ ++ unsigned long flags; ++ struct dmabounce_check_entry *entry = ++ kzalloc(sizeof(struct dmabounce_check_entry), GFP_ATOMIC); ++ ++ if (!entry) ++ return ENOMEM; ++ ++ INIT_LIST_HEAD(&entry->list); ++ entry->checker = function; ++ entry->data = data; ++ ++ write_lock_irqsave(&checkers_lock, flags); ++ list_add(&entry->list, &checkers); ++ write_unlock_irqrestore(&checkers_lock, flags); ++ ++ return 0; ++} ++ ++void ++dmabounce_remove_checker(dmabounce_check function, void *data) ++{ ++ unsigned long flags; ++ struct list_head *pos; ++ ++ write_lock_irqsave(&checkers_lock, flags); ++ __list_for_each(pos, &checkers) { ++ struct dmabounce_check_entry *entry = container_of(pos, ++ struct dmabounce_check_entry, list); ++ if (entry->checker == function && entry->data == data) { ++ list_del(pos); ++ write_unlock_irqrestore(&checkers_lock, flags); ++ kfree(entry); ++ return; ++ } ++ } ++ ++ write_unlock_irqrestore(&checkers_lock, flags); ++ printk(KERN_WARNING "dmabounce checker not found: %p\n", function); ++} ++ ++static int dma_needs_bounce(struct device *dev, dma_addr_t dma, size_t size) ++{ ++ unsigned long flags; ++ struct list_head *pos; ++ ++ read_lock_irqsave(&checkers_lock, flags); ++ __list_for_each(pos, &checkers) { ++ struct dmabounce_check_entry *entry = container_of(pos, ++ struct dmabounce_check_entry, list); ++ if (entry->checker(dev, dma, size, entry->data)) { ++ read_unlock_irqrestore(&checkers_lock, flags); ++ return 1; ++ } ++ } ++ ++ read_unlock_irqrestore(&checkers_lock, flags); ++#ifdef CONFIG_PLATFORM_DMABOUNCE ++ return platform_dma_needs_bounce(dev, dma, size); ++#else ++ return 0; ++#endif ++} + #ifdef STATS + static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr, + char *buf) +@@ -239,7 +315,7 @@ map_single(struct device *dev, void *ptr, size_t size, + struct safe_buffer *buf; + + buf = alloc_safe_buffer(device_info, ptr, size, dir); +- if (buf == 0) { ++ if (buf == NULL) { + dev_err(dev, "%s: unable to map unsafe buffer %p!\n", + __func__, ptr); + return 0; +@@ -643,7 +719,6 @@ dmabounce_unregister_dev(struct device *dev) + dev->bus_id, dev->bus->name); + } + +- + EXPORT_SYMBOL(dma_map_single); + EXPORT_SYMBOL(dma_unmap_single); + EXPORT_SYMBOL(dma_map_sg); +@@ -653,6 +728,9 @@ EXPORT_SYMBOL(dma_sync_single_for_device); + EXPORT_SYMBOL(dma_sync_sg); + EXPORT_SYMBOL(dmabounce_register_dev); + EXPORT_SYMBOL(dmabounce_unregister_dev); ++EXPORT_SYMBOL(dmabounce_register_checker); ++EXPORT_SYMBOL(dmabounce_remove_checker); ++ + + MODULE_AUTHOR("Christopher Hoover , Deepak Saxena "); + MODULE_DESCRIPTION("Special dma_{map/unmap/dma_sync}_* routines for systems with limited DMA windows"); +diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c +index eb06d0b..3b8fbdd 100644 +--- a/arch/arm/common/sa1111.c ++++ b/arch/arm/common/sa1111.c +@@ -778,7 +778,7 @@ static void __sa1111_remove(struct sa1111 *sachip) + * This should only get called for sa1111_device types due to the + * way we configure our device dma_masks. + */ +-int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size) ++int platform_dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size) + { + /* + * Section 4.6 of the "Intel StrongARM SA-1111 Development Module +diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig +index 61b2dfc..5870371 100644 +--- a/arch/arm/mach-ixp4xx/Kconfig ++++ b/arch/arm/mach-ixp4xx/Kconfig +@@ -161,6 +161,7 @@ comment "IXP4xx Options" + config DMABOUNCE + bool + default y ++ select PLATFORM_DMABOUNCE + depends on PCI + + config IXP4XX_INDIRECT_PCI +diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c +index bf04121..ac46492 100644 +--- a/arch/arm/mach-ixp4xx/common-pci.c ++++ b/arch/arm/mach-ixp4xx/common-pci.c +@@ -336,7 +336,7 @@ static int ixp4xx_pci_platform_notify_remove(struct device *dev) + return 0; + } + +-int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) ++int platform_dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) + { + return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M); + } +-- +1.5.3.8 + diff --git a/packages/linux/linux-rp-2.6.24/tosa/0002-Modify-dma_alloc_coherent-on-ARM-so-that-it-supports.patch b/packages/linux/linux-rp-2.6.24/tosa/0002-Modify-dma_alloc_coherent-on-ARM-so-that-it-supports.patch new file mode 100644 index 0000000000..a562ef921b --- /dev/null +++ b/packages/linux/linux-rp-2.6.24/tosa/0002-Modify-dma_alloc_coherent-on-ARM-so-that-it-supports.patch @@ -0,0 +1,260 @@ +From 8e95f90487d2fb46fd862744ddb34f47c30b0c5a Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 4 Jan 2008 18:27:50 +0000 +Subject: [PATCH 02/64] Modify dma_alloc_coherent on ARM so that it supports device local DMA. + +--- + arch/arm/mm/consistent.c | 125 +++++++++++++++++++++++++++++++++++++++++ + include/asm-arm/dma-mapping.h | 37 +++++++------ + 2 files changed, 145 insertions(+), 17 deletions(-) + +diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c +index 333a82a..3da0f94 100644 +--- a/arch/arm/mm/consistent.c ++++ b/arch/arm/mm/consistent.c +@@ -3,6 +3,8 @@ + * + * Copyright (C) 2000-2004 Russell King + * ++ * Device local coherent memory support added by Ian Molton (spyro@f2s.com) ++ * + * 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. +@@ -20,6 +22,7 @@ + + #include + #include ++#include + #include + #include + +@@ -35,6 +38,13 @@ + #define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) + #define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) + ++struct dma_coherent_mem { ++ void *virt_base; ++ u32 device_base; ++ int size; ++ int flags; ++ unsigned long *bitmap; ++}; + + /* + * These are the page tables (2MB each) covering uncached, DMA consistent allocations +@@ -153,6 +163,13 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, + unsigned long order; + u64 mask = ISA_DMA_THRESHOLD, limit; + ++ /* Following is a work-around (a.k.a. hack) to prevent pages ++ * with __GFP_COMP being passed to split_page() which cannot ++ * handle them. The real problem is that this flag probably ++ * should be 0 on ARM as it is not supported on this ++ * platform--see CONFIG_HUGETLB_PAGE. */ ++ gfp &= ~(__GFP_COMP); ++ + if (!consistent_pte[0]) { + printk(KERN_ERR "%s: not initialised\n", __func__); + dump_stack(); +@@ -160,6 +177,26 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, + } + + if (dev) { ++ ++ if (dev->dma_mem) { ++ unsigned long flags; ++ int pgnum; ++ void *ret; ++ ++ spin_lock_irqsave(&consistent_lock, flags); ++ pgnum = bitmap_find_free_region(dev->dma_mem->bitmap, ++ dev->dma_mem->size, ++ get_order(size)); ++ spin_unlock_irqrestore(&consistent_lock, flags); ++ ++ if (pgnum >= 0) { ++ *handle = dev->dma_mem->device_base + (pgnum << PAGE_SHIFT); ++ ret = dev->dma_mem->virt_base + (pgnum << PAGE_SHIFT); ++ memset(ret, 0, size); ++ return ret; ++ } ++ } ++ + mask = dev->coherent_dma_mask; + + /* +@@ -177,6 +214,9 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, + mask, (unsigned long long)ISA_DMA_THRESHOLD); + goto no_page; + } ++ ++ if (dev->dma_mem && dev->dma_mem->flags & DMA_MEMORY_EXCLUSIVE) ++ return NULL; + } + + /* +@@ -359,6 +399,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr + pte_t *ptep; + int idx; + u32 off; ++ struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; ++ unsigned long order; + + WARN_ON(irqs_disabled()); + +@@ -368,6 +410,15 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr + } + + size = PAGE_ALIGN(size); ++ order = get_order(size); ++ ++ /* What if mem is valid and the range is not? */ ++ if (mem && cpu_addr >= mem->virt_base && cpu_addr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { ++ int page = (cpu_addr - mem->virt_base) >> PAGE_SHIFT; ++ ++ bitmap_release_region(mem->bitmap, page, order); ++ return; ++ } + + spin_lock_irqsave(&consistent_lock, flags); + c = vm_region_find(&consistent_head, (unsigned long)cpu_addr); +@@ -437,6 +488,80 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr + } + EXPORT_SYMBOL(dma_free_coherent); + ++int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, ++ dma_addr_t device_addr, size_t size, int flags) ++{ ++ void __iomem *mem_base; ++ int pages = size >> PAGE_SHIFT; ++ int bitmap_size = (pages + 31)/32; ++ ++ if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0) ++ goto out; ++ if (!size) ++ goto out; ++ if (dev->dma_mem) ++ goto out; ++ ++ /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ ++ mem_base = ioremap_nocache(bus_addr, size); ++ if (!mem_base) ++ goto out; ++ ++ dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); ++ if (!dev->dma_mem) ++ goto out; ++ memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem)); ++ dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); ++ if (!dev->dma_mem->bitmap) ++ goto free1_out; ++ ++ dev->dma_mem->virt_base = mem_base; ++ dev->dma_mem->device_base = device_addr; ++ dev->dma_mem->size = pages; ++ dev->dma_mem->flags = flags; ++ ++ if (flags & DMA_MEMORY_MAP) ++ return DMA_MEMORY_MAP; ++ ++ return DMA_MEMORY_IO; ++ ++ free1_out: ++ kfree(dev->dma_mem->bitmap); ++ out: ++ return 0; ++} ++EXPORT_SYMBOL(dma_declare_coherent_memory); ++ ++void dma_release_declared_memory(struct device *dev) ++{ ++ struct dma_coherent_mem *mem = dev->dma_mem; ++ ++ if (!mem) ++ return; ++ dev->dma_mem = NULL; ++ kfree(mem->bitmap); ++ kfree(mem); ++} ++EXPORT_SYMBOL(dma_release_declared_memory); ++ ++void *dma_mark_declared_memory_occupied(struct device *dev, ++ dma_addr_t device_addr, size_t size) ++{ ++ struct dma_coherent_mem *mem = dev->dma_mem; ++ int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; ++ int pos, err; ++ ++ if (!mem) ++ return ERR_PTR(-EINVAL); ++ ++ pos = (device_addr - mem->device_base) >> PAGE_SHIFT; ++ err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages)); ++ if (err != 0) ++ return ERR_PTR(err); ++ return mem->virt_base + (pos << PAGE_SHIFT); ++} ++EXPORT_SYMBOL(dma_mark_declared_memory_occupied); ++ + /* + * Initialise the consistent memory allocation. + */ +diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h +index e99406a..f18ba05 100644 +--- a/include/asm-arm/dma-mapping.h ++++ b/include/asm-arm/dma-mapping.h +@@ -7,6 +7,19 @@ + + #include + ++#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY ++extern int ++dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, ++ dma_addr_t device_addr, size_t size, int flags); ++ ++extern void ++dma_release_declared_memory(struct device *dev); ++ ++extern void * ++dma_mark_declared_memory_occupied(struct device *dev, ++ dma_addr_t device_addr, size_t size); ++ ++ + /* + * DMA-consistent mapping functions. These allocate/free a region of + * uncached, unwrite-buffered mapped memory space for use with DMA +@@ -433,23 +446,13 @@ extern int dmabounce_register_dev(struct device *, unsigned long, unsigned long) + */ + extern void dmabounce_unregister_dev(struct device *); + +-/** +- * dma_needs_bounce +- * +- * @dev: valid struct device pointer +- * @dma_handle: dma_handle of unbounced buffer +- * @size: size of region being mapped +- * +- * Platforms that utilize the dmabounce mechanism must implement +- * this function. +- * +- * The dmabounce routines call this function whenever a dma-mapping +- * is requested to determine whether a given buffer needs to be bounced +- * or not. The function must return 0 if the buffer is OK for +- * DMA access and 1 if the buffer needs to be bounced. +- * +- */ +-extern int dma_needs_bounce(struct device*, dma_addr_t, size_t); ++typedef int (*dmabounce_check)(struct device *dev, dma_addr_t dma, size_t size, void *data); ++extern int dmabounce_register_checker(dmabounce_check, void *data); ++extern void dmabounce_remove_checker(dmabounce_check, void *data); ++#ifdef CONFIG_PLATFORM_DMABOUNCE ++extern int platform_dma_needs_bounce(struct device *dev, dma_addr_t dma, size_t size, void *data); ++#endif ++ + #endif /* CONFIG_DMABOUNCE */ + + #endif /* __KERNEL__ */ +-- +1.5.3.8 + diff --git a/packages/linux/linux-rp-2.6.24/tosa/0003-Core-MFD-support.patch b/packages/linux/linux-rp-2.6.24/tosa/0003-Core-MFD-support.patch new file mode 100644 index 0000000000..d84a4f7835 --- /dev/null +++ b/packages/linux/linux-rp-2.6.24/tosa/0003-Core-MFD-support.patch @@ -0,0 +1,243 @@ +From a07910753f9965842b6647f0561db125b538f5ed Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 4 Jan 2008 18:32:44 +0000 +Subject: [PATCH 03/64] Core MFD support + +This patch provides a common subdevice registration system for MFD type +chips, using platfrom device. + +It also provides a new resource type for IRQs such that a subdevices IRQ may +be computed based on the MFD cores IRQ handler, since many MFDs provide an IRQ +multiplex. +--- + drivers/mfd/Kconfig | 4 ++ + drivers/mfd/Makefile | 2 + + drivers/mfd/mfd-core.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/ioport.h | 1 + + include/linux/mfd-core.h | 51 ++++++++++++++++++++ + 5 files changed, 174 insertions(+), 0 deletions(-) + create mode 100644 drivers/mfd/mfd-core.c + create mode 100644 include/linux/mfd-core.h + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 2571619..1205c89 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -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--- +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 5143209..6c20064 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -4,6 +4,8 @@ + + obj-$(CONFIG_MFD_SM501) += sm501.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 +diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c +new file mode 100644 +index 0000000..88874e1 +--- /dev/null ++++ b/drivers/mfd/mfd-core.c +@@ -0,0 +1,116 @@ ++/* ++ * drivers/mfd/mfd-core.c ++ * ++ * 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 ++#include ++#include ++ ++#define SIGNED_SHIFT(val, shift) ((shift) >= 0 ? \ ++ ((val) << (shift)) : \ ++ ((val) >> -(shift))) ++ ++int mfd_add_devices( ++ struct platform_device *parent, ++ const struct mfd_cell *cells, int n_devs, ++ struct resource *mem, ++ int relative_addr_shift, ++ int irq_base) ++{ ++ int i; ++ ++ for (i = 0; i < n_devs; i++) { ++ struct resource *res = NULL; ++ const struct mfd_cell *cell = cells + i; ++ struct platform_device *pdev; ++ int ret = -ENOMEM; ++ int r; ++ ++ pdev = platform_device_alloc(cell->name, -1); ++ if (!pdev) ++ goto fail_alloc; ++ ++ pdev->dev.uevent_suppress = 0; ++ pdev->dev.parent = &parent->dev; ++ ++ ret = platform_device_add_data(pdev, &cell, sizeof(struct mfd_cell *)); ++ if (ret) ++ goto fail_device; ++ ++ res = kzalloc(cell->num_resources * sizeof(struct resource), ++ GFP_KERNEL); ++ if (!res) ++ goto fail_device; ++ ++ for (r = 0; r < cell->num_resources; r++) { ++ res[r].name = cell->resources[r].name; ++ ++ /* Find out base to use */ ++ if (cell->resources[r].flags & IORESOURCE_MEM) { ++ res[r].parent = mem; ++ res[r].start = mem->start + ++ SIGNED_SHIFT(cell->resources[r].start, ++ relative_addr_shift); ++ res[r].end = mem->start + ++ SIGNED_SHIFT(cell->resources[r].end, ++ relative_addr_shift); ++ } else if ((cell->resources[r].flags & IORESOURCE_IRQ) && ++ (cell->resources[r].flags & IORESOURCE_IRQ_MFD_SUBDEVICE)) { ++ res[r].start = irq_base + ++ cell->resources[r].start; ++ res[r].end = irq_base + ++ cell->resources[r].end; ++ } else { ++ res[r].start = cell->resources[r].start; ++ res[r].end = cell->resources[r].end; ++ } ++ ++ res[r].flags = cell->resources[r].flags; ++ } ++ ++ ret = platform_device_add_resources(pdev, ++ res, ++ cell->num_resources); ++ kfree(res); ++ ++ if (ret) ++ goto fail_device; ++ ++ ret = platform_device_add(pdev); ++ ++ if (ret) { ++ platform_device_del(pdev); ++fail_device: ++ platform_device_put(pdev); ++fail_alloc: ++ mfd_remove_devices(parent); ++ return ret; ++ } ++ } ++ return 0; ++} ++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"); +diff --git a/include/linux/ioport.h b/include/linux/ioport.h +index 6187a85..0348c71 100644 +--- a/include/linux/ioport.h ++++ b/include/linux/ioport.h +@@ -56,6 +56,7 @@ struct resource_list { + #define IORESOURCE_IRQ_HIGHLEVEL (1<<2) + #define IORESOURCE_IRQ_LOWLEVEL (1<<3) + #define IORESOURCE_IRQ_SHAREABLE (1<<4) ++#define IORESOURCE_IRQ_MFD_SUBDEVICE (1<<5) + + /* ISA PnP DMA specific bits (IORESOURCE_BITS) */ + #define IORESOURCE_DMA_TYPE_MASK (3<<0) +diff --git a/include/linux/mfd-core.h b/include/linux/mfd-core.h +new file mode 100644 +index 0000000..0e9de78 +--- /dev/null ++++ b/include/linux/mfd-core.h +@@ -0,0 +1,51 @@ ++#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 ++ ++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; /* data passed to drivers */ ++ ++ /* ++ * 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 __maybe_unused 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, ++ int relative_addr_shift, ++ int irq_base); ++ ++extern void mfd_remove_devices(struct platform_device *parent); ++ ++#endif +-- +1.5.3.8 + diff --git a/packages/linux/linux-rp-2.6.24/tosa/0004-Add-support-for-tc6393xb-MFD-core.patch b/packages/linux/linux-rp-2.6.24/tosa/0004-Add-support-for-tc6393xb-MFD-core.patch new file mode 100644 index 0000000000..a78c0f37f3 --- /dev/null +++ b/packages/linux/linux-rp-2.6.24/tosa/0004-Add-support-for-tc6393xb-MFD-core.patch @@ -0,0 +1,907 @@ +From 3f56cac281fb407b7d8e574d18ee7d72aa7e7c28 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Sat, 29 Dec 2007 15:02:30 +0000 +Subject: [PATCH 04/64] Add support for tc6393xb MFD core + +--- + drivers/mfd/Kconfig | 6 + + drivers/mfd/Makefile | 2 + + drivers/mfd/tc6393xb.c | 740 ++++++++++++++++++++++++++++++++++++++++++ + include/linux/mfd/tc6393xb.h | 108 ++++++ + 4 files changed, 856 insertions(+), 0 deletions(-) + create mode 100644 drivers/mfd/tc6393xb.c + create mode 100644 include/linux/mfd/tc6393xb.h + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 1205c89..9903d0a 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -9,6 +9,12 @@ config MFD_CORE + tristate + default n + ++config MFD_TC6393XB ++ bool "Support Toshiba TC6393XB" ++ select MFD_CORE ++ help ++ Support for Toshiba Mobile IO Controller TC6393XB ++ + config MFD_SM501 + tristate "Support for Silicon Motion SM501" + ---help--- +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 6c20064..ffd342e 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -6,6 +6,8 @@ obj-$(CONFIG_MFD_SM501) += sm501.o + + obj-$(CONFIG_MFD_CORE) += mfd-core.o + ++obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o ++ + obj-$(CONFIG_MCP) += mcp-core.o + obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o + obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o +diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c +new file mode 100644 +index 0000000..9439f39 +--- /dev/null ++++ b/drivers/mfd/tc6393xb.c +@@ -0,0 +1,740 @@ ++/* ++ * Toshiba TC6393XB SoC support ++ * ++ * Copyright(c) 2005-2006 Chris Humbert ++ * Copyright(c) 2005 Dirk Opfer ++ * Copyright(c) 2005 Ian Molton ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct tc6393xb_scr { ++ u8 x00[8]; ++ u8 revid; /* 0x08 Revision ID */ ++ u8 x01[0x47]; ++ u8 isr; /* 0x50 Interrupt Status */ ++ u8 x02; ++ u8 imr; /* 0x52 Interrupt Mask */ ++ u8 x03; ++ u8 irr; /* 0x54 Interrupt Routing */ ++ u8 x04[0x0b]; ++ u16 gper; /* 0x60 GP Enable */ ++ u8 x05[2]; ++ u16 gpi_sr[2]; /* 0x64 GPI Status */ ++ u16 gpi_imr[2]; /* 0x68 GPI INT Mask */ ++ u16 gpi_eder[2]; /* 0x6c GPI Edge Detect Enable */ ++ u16 gpi_lir[4]; /* 0x70 GPI Level Invert */ ++ u16 gpo_dsr[2]; /* 0x78 GPO Data Set */ ++ u16 gpo_doecr[2]; /* 0x7c GPO Data OE Control */ ++ u16 gp_iarcr[2]; /* 0x80 GP Internal Active Reg Control */ ++ u16 gp_iarlcr[2]; /* 0x84 GP Internal Active Reg Level Con*/ ++ u8 gpi_bcr[4]; /* 0x88 GPI Buffer Control */ ++ u16 gpa_iarcr; /* 0x8c GPa Internal Active Reg Control */ ++ u8 x06[2]; ++ u16 gpa_iarlcr; /* 0x90 GPa Internal Active Reg Level Co*/ ++ u8 x07[2]; ++ u16 gpa_bcr; /* 0x94 GPa Buffer Control */ ++ u8 x08[2]; ++ u16 ccr; /* 0x98 Clock Control */ ++ u16 pll2cr; /* 0x9a PLL2 Control */ ++ u16 pll1cr[2]; /* 0x9c PLL1 Control */ ++ u8 diarcr; /* 0xa0 Device Internal Active Reg Contr*/ ++ u8 dbocr; /* 0xa1 Device Buffer Off Control */ ++ u8 x09[0x3e]; ++ u8 fer; /* 0xe0 Function Enable */ ++ u8 x10[3]; ++ u16 mcr; /* 0xe4 Mode Control */ ++ u8 x11[0x14]; ++ u8 config; /* 0xfc Configuration Control */ ++ u8 x12[2]; ++ u8 debug; /* 0xff Debug */ ++} __attribute__ ((packed)); ++ ++/*--------------------------------------------------------------------------*/ ++ ++struct tc6393xb { ++ struct tc6393xb_scr __iomem *scr; ++ ++ spinlock_t lock; /* protects RMW cycles */ ++ ++ struct { ++ union tc6393xb_scr_fer fer; ++ union tc6393xb_scr_ccr ccr; ++ u8 gpi_bcr[4]; ++ } suspend_state; ++ ++ struct resource rscr; ++ struct resource *iomem; ++ int irq; ++}; ++ ++/*--------------------------------------------------------------------------*/ ++ ++static int tc6393xb_mmc_enable(struct platform_device *mmc) { ++ struct platform_device *dev = to_platform_device(mmc->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_ccr ccr; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ccr.raw = ioread16(&scr->ccr); ++ ccr.bits.ck32ken = 1; ++ iowrite16(ccr.raw, &scr->ccr); ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++static int tc6393xb_mmc_disable(struct platform_device *mmc) { ++ struct platform_device *dev = to_platform_device(mmc->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_ccr ccr; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ccr.raw = ioread16(&scr->ccr); ++ ccr.bits.ck32ken = 0; ++ iowrite16(ccr.raw, &scr->ccr); ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++ ++static int tc6393xb_nand_disable(struct platform_device *nand) ++{ ++ return 0; ++} ++ ++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); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ /* SMD buffer on */ ++ dev_dbg(&dev->dev, "SMD buffer on\n"); ++ iowrite8(0xff, scr->gpi_bcr + 1); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++int tc6393xb_lcd_set_power(struct platform_device *fb, bool on) ++{ ++ struct platform_device *dev = to_platform_device(fb->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_fer fer; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ fer.raw = ioread8(&scr->fer); ++ fer.bits.slcden = on ? 1 : 0; ++ iowrite8(fer.raw, &scr->fer); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL(tc6393xb_lcd_set_power); ++ ++int tc6393xb_lcd_mode(struct platform_device *fb_dev, ++ struct fb_videomode *mode) { ++ struct tc6393xb *tc6393xb = ++ platform_get_drvdata(to_platform_device(fb_dev->dev.parent)); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ ++ iowrite16(mode->pixclock, scr->pll1cr + 0); ++ iowrite16(mode->pixclock >> 16, scr->pll1cr + 1); ++ ++ return 0; ++} ++EXPORT_SYMBOL(tc6393xb_lcd_mode); ++ ++static int tc6393xb_ohci_disable(struct platform_device *ohci) ++{ ++ struct platform_device *dev = to_platform_device(ohci->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_ccr ccr; ++ union tc6393xb_scr_fer fer; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ fer.raw = ioread8(&scr->fer); ++ fer.bits.usben = 0; ++ iowrite8(fer.raw, &scr->fer); ++ ++ ccr.raw = ioread16(&scr->ccr); ++ ccr.bits.usbcken = 0; ++ iowrite16(ccr.raw, &scr->ccr); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++static int tc6393xb_ohci_enable(struct platform_device *ohci) ++{ ++ struct platform_device *dev = to_platform_device(ohci->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_ccr ccr; ++ union tc6393xb_scr_fer fer; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ ccr.raw = ioread16(&scr->ccr); ++ ccr.bits.usbcken = 1; ++ iowrite16(ccr.raw, &scr->ccr); ++ ++ fer.raw = ioread8(&scr->fer); ++ fer.bits.usben = 1; ++ iowrite8(fer.raw, &scr->fer); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++static int tc6393xb_fb_disable(struct platform_device *fb) ++{ ++ struct platform_device *dev = to_platform_device(fb->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_ccr ccr; ++ union tc6393xb_scr_fer fer; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ /* ++ * FIXME: is this correct or it should be moved to other _disable? ++ */ ++ fer.raw = ioread8(&scr->fer); ++ fer.bits.slcden = 0; ++/* fer.bits.lcdcven = 0; */ ++ iowrite8(fer.raw, &scr->fer); ++ ++ ccr.raw = ioread16(&scr->ccr); ++ ccr.bits.mclksel = disable; ++ iowrite16(ccr.raw, &scr->ccr); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++static int tc6393xb_fb_enable(struct platform_device *fb) ++{ ++ struct platform_device *dev = to_platform_device(fb->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_ccr ccr; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ ccr.raw = ioread16(&scr->ccr); ++ ccr.bits.mclksel = m48MHz; ++ iowrite16(ccr.raw, &scr->ccr); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++static int tc6393xb_fb_suspend(struct platform_device *fb) ++{ ++ struct platform_device *dev = to_platform_device(fb->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_ccr ccr; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ ccr.raw = ioread16(&scr->ccr); ++ ccr.bits.mclksel = disable; ++ iowrite16(ccr.raw, &scr->ccr); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++static int tc6393xb_fb_resume(struct platform_device *fb) ++{ ++ struct platform_device *dev = to_platform_device(fb->dev.parent); ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ union tc6393xb_scr_ccr ccr; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ ccr.raw = ioread16(&scr->ccr); ++ ccr.bits.mclksel = m48MHz; ++ iowrite16(ccr.raw, &scr->ccr); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++static struct resource tc6393xb_mmc_resources[] = { ++ { ++ .name = TMIO_MMC_CONTROL, ++ .start = 0x800, ++ .end = 0x9ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_MMC_CONFIG, ++ .start = 0x200, ++ .end = 0x2ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_MMC_IRQ, ++ .start = IRQ_TC6393_MMC, ++ .end = IRQ_TC6393_MMC, ++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_MFD_SUBDEVICE, ++ }, ++}; ++ ++const static struct resource 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 | IORESOURCE_IRQ_MFD_SUBDEVICE, ++ }, ++}; ++ ++const static struct resource tc6393xb_ohci_resources[] = { ++ { ++ .name = TMIO_OHCI_CONFIG, ++ .start = 0x0300, ++ .end = 0x03ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_OHCI_CONTROL, ++ .start = 0x3000, ++ .end = 0x31ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_OHCI_SRAM, ++ .start = 0x010000, ++ .end = 0x017fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_OHCI_SRAM_ALIAS, ++ .start = 0x018000, ++ .end = 0x01ffff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_OHCI_IRQ, ++ .start = IRQ_TC6393_OHCI, ++ .end = IRQ_TC6393_OHCI, ++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_MFD_SUBDEVICE, ++ }, ++}; ++ ++const static struct resource tc6393xb_fb_resources[] = { ++ { ++ .name = TMIO_FB_CONFIG, ++ .start = 0x0500, ++ .end = 0x05ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_FB_CONTROL, ++ .start = 0x5000, ++ .end = 0x51ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_FB_VRAM, ++ .start = 0x100000, ++ .end = 0x1fffff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_FB_IRQ, ++ .start = IRQ_TC6393_FB, ++ .end = IRQ_TC6393_FB, ++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_MFD_SUBDEVICE, ++ }, ++}; ++ ++static struct mfd_cell tc6393xb_cells[] = { ++ { ++ .name = "tmio-nand", ++ .enable = tc6393xb_nand_enable, ++ .disable = tc6393xb_nand_disable, ++ .num_resources = ARRAY_SIZE(tc6393xb_nand_resources), ++ .resources = tc6393xb_nand_resources, ++ }, ++ { ++ .name = "tmio-ohci", ++ .enable = tc6393xb_ohci_enable, ++ .disable = tc6393xb_ohci_disable, ++ .num_resources = ARRAY_SIZE(tc6393xb_ohci_resources), ++ .resources = tc6393xb_ohci_resources, ++ }, ++ { ++ .name = "tmio-fb", ++ .enable = tc6393xb_fb_enable, ++ .disable = tc6393xb_fb_disable, ++ .suspend = tc6393xb_fb_suspend, ++ .resume = tc6393xb_fb_resume, ++ .num_resources = ARRAY_SIZE(tc6393xb_fb_resources), ++ .resources = tc6393xb_fb_resources, ++ }, ++ { ++ .name = "tmio-mmc", ++ .enable = tc6393xb_mmc_enable, ++ .disable = tc6393xb_mmc_disable, ++ .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), ++ .resources = tc6393xb_mmc_resources, ++ }, ++}; ++ ++/*--------------------------------------------------------------------------*/ ++ ++static void ++tc6393xb_irq(unsigned int irq, struct irq_desc *desc) ++{ ++ struct platform_device *dev = get_irq_chip_data(irq); ++ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data; ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ unsigned int isr; ++ unsigned int i; ++ ++ desc->chip->ack(irq); ++ ++ while ((isr = ioread8(&scr->isr) & ~ioread8(&scr->imr))) ++ for (i = 0; i < TC6393XB_NR_IRQS; i++) { ++ if (isr & (1 << i)) ++ desc_handle_irq(tcpd->irq_base + i, ++ irq_desc + tcpd->irq_base + i); ++ } ++} ++ ++static void tc6393xb_irq_ack(unsigned int irq) ++{ ++} ++ ++static void tc6393xb_irq_mask(unsigned int irq) ++{ ++ struct platform_device *dev = get_irq_chip_data(irq); ++ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data; ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ iowrite8(ioread8(&scr->imr) | (1 << (irq - tcpd->irq_base)), ++ &scr->imr); ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++} ++ ++static void tc6393xb_irq_unmask(unsigned int irq) ++{ ++ struct platform_device *dev = get_irq_chip_data(irq); ++ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data; ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ iowrite8(ioread8(&scr->imr) & ~(1 << (irq - tcpd->irq_base)), ++ &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_platform_data *tcpd = dev->dev.platform_data; ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ unsigned int irq; ++ ++ for ( ++ irq = tcpd->irq_base; ++ irq <= tcpd->irq_base + TC6393XB_NR_IRQS; ++ irq++) { ++ set_irq_chip(irq, &tc6393xb_chip); ++ set_irq_chip_data(irq, dev); ++ set_irq_handler(irq, handle_edge_irq); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); ++ } ++ ++ set_irq_type(tc6393xb->irq, IRQT_FALLING); ++ set_irq_chip_data(tc6393xb->irq, dev); ++ set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq); ++} ++ ++static void tc6393xb_detach_irq(struct platform_device *dev) ++{ ++ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data; ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ unsigned int irq; ++ ++ set_irq_chained_handler(tc6393xb->irq, NULL); ++ set_irq_chip_data(tc6393xb->irq, NULL); ++ ++ for ( ++ irq = tcpd->irq_base; ++ irq <= tcpd->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, int resume) ++{ ++ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data; ++ struct tc6393xb *tc6393xb = platform_get_drvdata(dev); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ int ret; ++ int i; ++ ++ if (resume) ++ ret = tcpd->resume(dev); ++ else ++ ret = tcpd->enable(dev); ++ if (ret) ++ return ret; ++ ++ iowrite8(resume ? ++ tc6393xb->suspend_state.fer.raw : ++ 0, &scr->fer); ++ iowrite16(tcpd->scr_pll2cr, &scr->pll2cr); ++ iowrite16(resume? ++ tc6393xb->suspend_state.ccr.raw : ++ tcpd->scr_ccr.raw, &scr->ccr); ++ iowrite16(tcpd->scr_mcr.raw, &scr->mcr); ++ iowrite16(tcpd->scr_gper, &scr->gper); ++ iowrite8(0, &scr->irr); ++ iowrite8(0xbf, &scr->imr); ++ iowrite16(tcpd->scr_gpo_dsr, scr->gpo_dsr + 0); ++ iowrite16(tcpd->scr_gpo_dsr >> 16, scr->gpo_dsr + 1); ++ iowrite16(tcpd->scr_gpo_doecr, scr->gpo_doecr + 0); ++ iowrite16(tcpd->scr_gpo_doecr >> 16, scr->gpo_doecr + 1); ++ ++ if (resume) ++ for (i = 0; i < 4; i++) ++ iowrite8(tc6393xb->suspend_state.gpi_bcr[i], ++ 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; ++ ++ 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); ++ ++ 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 = tc6393xb_hw_init(dev, 0); ++ if (retval) ++ goto err_hw_init; ++ ++ printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n", ++ ioread8(&tc6393xb->scr->revid), ++ (unsigned long) iomem->start, tc6393xb->irq); ++ ++ if (tc6393xb->irq) ++ tc6393xb_attach_irq(dev); ++ ++ tc6393xb_cells[0].driver_data = tcpd->nand_data; ++ tc6393xb_cells[1].driver_data = NULL; /* tcpd->ohci_data; */ ++ tc6393xb_cells[2].driver_data = tcpd->fb_data; ++ ++ retval = mfd_add_devices(dev, ++ tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), ++ iomem, 0, tcpd->irq_base); ++ ++ if (retval == 0) ++ return 0; ++ ++ if (tc6393xb->irq) ++ tc6393xb_detach_irq(dev); ++ ++err_hw_init: ++ iounmap(tc6393xb->scr); ++err_ioremap: ++ release_resource(rscr); ++err_request_scr: ++ kfree(tc6393xb); ++err_kzalloc: ++ release_resource(iomem); ++ 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; ++ ++ if (tc6393xb->irq) ++ tc6393xb_detach_irq(dev); ++ ++ ret = tcpd->disable(dev); ++ ++ iounmap(tc6393xb->scr); ++ release_resource(&tc6393xb->rscr); ++ release_resource(tc6393xb->iomem); ++ ++ mfd_remove_devices(dev); ++ ++ platform_set_drvdata(dev, NULL); ++ ++ 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); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ int i; ++ ++ ++ tc6393xb->suspend_state.ccr.raw = ioread16(&scr->ccr); ++ tc6393xb->suspend_state.fer.raw = ioread8(&scr->fer); ++ for (i = 0; i < 4; i++) ++ tc6393xb->suspend_state.gpi_bcr[i] = ++ ioread8(scr->gpi_bcr + i); ++ ++ return tcpd->suspend(dev); ++} ++ ++static int tc6393xb_resume(struct platform_device *dev) ++{ ++ return tc6393xb_hw_init(dev, 1); ++} ++#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); ++} ++ ++module_init(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"); +diff --git a/include/linux/mfd/tc6393xb.h b/include/linux/mfd/tc6393xb.h +new file mode 100644 +index 0000000..e699294 +--- /dev/null ++++ b/include/linux/mfd/tc6393xb.h +@@ -0,0 +1,108 @@ ++/* ++ * Toshiba TC6393XB SoC support ++ * ++ * Copyright(c) 2005-2006 Chris Humbert ++ * Copyright(c) 2005 Dirk Opfer ++ * Copyright(c) 2005 Ian Molton ++ * 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 ++ ++#include ++#include ++ ++union tc6393xb_scr_fer { ++ u8 raw; ++struct { ++ unsigned usben:1; /* D0 USB enable */ ++ unsigned lcdcven:1; /* D1 polysylicon TFT enable */ ++ unsigned slcden:1; /* D2 SLCD enable */ ++} __attribute__ ((packed)) bits; ++} __attribute__ ((packed)); ++ ++union tc6393xb_scr_ccr { ++ u16 raw; ++struct { ++ unsigned ck32ken:1; /* D0 SD host clock enable */ ++ unsigned usbcken:1; /* D1 USB host clock enable */ ++ unsigned x00:2; ++ unsigned sharp:1; /* D4 ??? set in Sharp's code */ ++ unsigned x01:3; ++ enum { disable = 0, ++ m12MHz = 1, ++ m24MHz = 2, ++ m48MHz = 3, ++ } mclksel:3; /* D10-D8 LCD controller clock */ ++ unsigned x02:1; ++ enum { h24MHz = 0, ++ h48MHz = 1, ++ } hclksel:2; /* D13-D12 host bus clock */ ++ unsigned x03:2; ++} __attribute__ ((packed)) bits; ++} __attribute__ ((packed)); ++ ++enum pincontrol { ++ opendrain = 0, ++ tristate = 1, ++ pushpull = 2, ++ /* reserved = 3, */ ++}; ++ ++union tc6393xb_scr_mcr { ++ u16 raw; ++struct { ++ enum pincontrol rdyst:2; /* D1-D0 HRDY control */ ++ unsigned x00:1; ++ unsigned aren:1; /* D3 HRDY pull up resistance cut off */ ++ enum pincontrol intst:2; /* D5-D4 #HINT control */ ++ unsigned x01:1; ++ unsigned aien:1; /* D7 #HINT pull up resitance cut off */ ++ unsigned x02:8; ++} __attribute__ ((packed)) bits; ++} __attribute__ ((packed)); ++ ++struct tc6393xb_platform_data { ++ u16 scr_pll2cr; /* PLL2 Control */ ++ union tc6393xb_scr_ccr scr_ccr; /* Clock Control */ ++ union tc6393xb_scr_mcr scr_mcr; /* Mode 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 */ ++ ++ struct tmio_nand_data *nand_data; ++ struct tmio_fb_data *fb_data; ++}; ++ ++extern int tc6393xb_lcd_set_power(struct platform_device *fb_dev, bool on); ++extern int tc6393xb_lcd_mode(struct platform_device *fb_dev, ++ struct fb_videomode *mode); ++ ++ ++/* ++ * 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 +-- +1.5.3.8 + diff --git a/packages/linux/linux-rp-2.6.24/tosa/0005-Add-support-for-tc6387xb-MFD-core.patch b/packages/linux/linux-rp-2.6.24/tosa/0005-Add-support-for-tc6387xb-MFD-core.patch new file mode 100644 index 0000000000..7183e3af6d --- /dev/null +++ b/packages/linux/linux-rp-2.6.24/tosa/0005-Add-support-for-tc6387xb-MFD-core.patch @@ -0,0 +1,249 @@ +From a6a6faf1dbb90c950fe55a1719720457bfb5830a Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Sun, 16 Dec 2007 02:19:49 +0000 +Subject: [PATCH 05/64] Add support for tc6387xb MFD core + +--- + drivers/mfd/Kconfig | 6 ++ + drivers/mfd/Makefile | 1 + + drivers/mfd/tc6387xb.c | 163 ++++++++++++++++++++++++++++++++++++++++++ + include/linux/mfd/tc6387xb.h | 28 +++++++ + 4 files changed, 198 insertions(+), 0 deletions(-) + create mode 100644 drivers/mfd/tc6387xb.c + create mode 100644 include/linux/mfd/tc6387xb.h + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 9903d0a..1575323 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -9,6 +9,12 @@ config MFD_CORE + tristate + default n + ++config MFD_TC6387XB ++ bool "Support Toshiba TC6387XB" ++ select MFD_CORE ++ help ++ Support for Toshiba Mobile IO Controller TC6387XB ++ + config MFD_TC6393XB + bool "Support Toshiba TC6393XB" + select MFD_CORE +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index ffd342e..41b2190 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_MFD_SM501) += sm501.o + + obj-$(CONFIG_MFD_CORE) += mfd-core.o + ++obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o + obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o + + obj-$(CONFIG_MCP) += mcp-core.o +diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c +new file mode 100644 +index 0000000..c81fca2 +--- /dev/null ++++ b/drivers/mfd/tc6387xb.c +@@ -0,0 +1,163 @@ ++/* ++ * Toshiba TC6387XB support ++ * Copyright (c) 2005 Ian Molton ++ * ++ * 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 TC6387XB base support. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#ifdef CONFIG_PM ++static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ struct tc6387xb_platform_data *pdata = platform_get_drvdata(dev); ++ ++ if (pdata && pdata->suspend) ++ pdata->suspend(dev); ++ ++ return 0; ++} ++ ++static int tc6387xb_resume(struct platform_device *dev) ++{ ++ struct tc6387xb_platform_data *pdata = platform_get_drvdata(dev); ++ ++ if (pdata && pdata->resume) ++ pdata->resume(dev); ++ ++ return 0; ++} ++#else ++#define tc6387xb_suspend NULL ++#define tc6387xb_resume NULL ++#endif ++ ++/*--------------------------------------------------------------------------*/ ++ ++static int tc6387xb_mmc_enable(struct platform_device *mmc) { ++ struct platform_device *dev = to_platform_device(mmc->dev.parent); ++ struct tc6387xb_platform_data *tc6387xb = dev->dev.platform_data; ++ ++ if(tc6387xb->enable_mmc_clock) ++ tc6387xb->enable_mmc_clock(dev); ++ ++ return 0; ++} ++ ++static int tc6387xb_mmc_disable(struct platform_device *mmc) { ++ struct platform_device *dev = to_platform_device(mmc->dev.parent); ++ struct tc6387xb_platform_data *tc6387xb = dev->dev.platform_data; ++ ++ if(tc6387xb->disable_mmc_clock) ++ tc6387xb->disable_mmc_clock(dev); ++ ++ return 0; ++} ++ ++ ++/*--------------------------------------------------------------------------*/ ++ ++static struct resource tc6387xb_mmc_resources[] = { ++ { ++ .name = TMIO_MMC_CONTROL, ++ .start = 0x800, ++ .end = 0x9ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_MMC_CONFIG, ++ .start = 0x200, ++ .end = 0x2ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = TMIO_MMC_IRQ, ++ .start = 0, ++ .end = 0, ++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_MFD_SUBDEVICE, ++ }, ++}; ++ ++static struct mfd_cell tc6387xb_cells[] = { ++ { ++ .name = "tmio-mmc", ++ .enable = tc6387xb_mmc_enable, ++ .disable = tc6387xb_mmc_disable, ++ .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources), ++ .resources = tc6387xb_mmc_resources, ++ }, ++}; ++ ++static int tc6387xb_probe(struct platform_device *dev) ++{ ++ struct tc6387xb_platform_data *data = platform_get_drvdata(dev); ++ struct resource *iomem; ++ int irq; ++ ++ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ if (!iomem) ++ return -EINVAL; ++ ++ irq = platform_get_irq(dev, 0); ++ ++ if(data && data->enable) ++ data->enable(dev); ++ ++ printk(KERN_INFO "Toshiba tc6393xb initialised\n"); ++ ++ return mfd_add_devices(dev, tc6387xb_cells, ARRAY_SIZE(tc6387xb_cells), ++ iomem, 0, irq); ++} ++ ++static int tc6387xb_remove(struct platform_device *dev) ++{ ++ struct tc6387xb_platform_data *data = platform_get_drvdata(dev); ++ ++ if(data && data->disable) ++ data->disable(dev); ++ ++ return 0; ++} ++ ++ ++static struct platform_driver tc6387xb_platform_driver = { ++ .driver = { ++ .name = "tc6387xb", ++ }, ++ .probe = tc6387xb_probe, ++ .remove = tc6387xb_remove, ++ .suspend = tc6387xb_suspend, ++ .resume = tc6387xb_resume, ++}; ++ ++ ++static int __init tc6387xb_init(void) ++{ ++ return platform_driver_register (&tc6387xb_platform_driver); ++} ++ ++static void __exit tc6387xb_exit(void) ++{ ++ platform_driver_unregister(&tc6387xb_platform_driver); ++} ++ ++module_init(tc6387xb_init); ++module_exit(tc6387xb_exi