source: trunk/target/linux/s3c24xx/patches-2.6.30/001-merge-openmoko.patch @ 16048

Last change on this file since 16048 was 16048, checked in by kaloz, 7 years ago

update to 2.6.30-rc7

File size: 57.7 KB
  • new file arch/arm/mach-s3c2410/include/mach/mci.h

    Merge OpenMoko kernel patches
    git://git.openmoko.org/git/kernel.git#(no
    
    lars@lars-laptop   Thu May 14 18:33:23 UTC 2009
    
    ---
    
    - +  
     1#ifndef _ARCH_MCI_H 
     2#define _ARCH_MCI_H 
     3 
     4struct s3c24xx_mci_pdata { 
     5        unsigned int    gpio_detect; 
     6        unsigned int    gpio_wprotect; 
     7        unsigned long   ocr_avail; 
     8        unsigned int    do_dma; 
     9        void            (*set_power)(unsigned char power_mode, 
     10                                     unsigned short vdd); 
     11}; 
     12 
     13#endif /* _ARCH_NCI_H */ 
  • arch/arm/mach-s3c2410/include/mach/regs-sdi.h

    a b  
    3030#define S3C2410_SDIFSTA               (0x38) 
    3131 
    3232#define S3C2410_SDIDATA               (0x3C) 
     33#define S3C2410_SDIDATA_BYTE          (0x3C) 
    3334#define S3C2410_SDIIMSK               (0x40) 
    3435 
    3536#define S3C2440_SDIDATA               (0x40) 
     
    3738 
    3839#define S3C2440_SDICON_SDRESET        (1<<8) 
    3940#define S3C2440_SDICON_MMCCLOCK       (1<<5) 
     41#define S3C2440_SDIDATA_BYTE          (0x48) 
     42 
    4043#define S3C2410_SDICON_BYTEORDER      (1<<4) 
    4144#define S3C2410_SDICON_SDIOIRQ        (1<<3) 
    4245#define S3C2410_SDICON_RWAITEN        (1<<2) 
  • arch/arm/mach-s3c2440/s3c2440.c

    a b int __init s3c2440_init(void) 
    4646        s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT; 
    4747        s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT; 
    4848 
     49        /* make sure SD/MMC driver can distinguish 2440 from 2410 */ 
     50        s3c_device_sdi.name = "s3c2440-sdi"; 
     51 
    4952        /* register our system device for everything else */ 
    5053 
    5154        return sysdev_register(&s3c2440_sysdev); 
  • arch/arm/mach-s3c2442/s3c2442.c

    a b  
    2121 
    2222#include <plat/s3c2442.h> 
    2323#include <plat/cpu.h> 
     24#include <plat/devs.h> 
    2425 
    2526static struct sys_device s3c2442_sysdev = { 
    2627        .cls            = &s3c2442_sysclass, 
    int __init s3c2442_init(void) 
    3031{ 
    3132        printk("S3C2442: Initialising architecture\n"); 
    3233 
     34        /* make sure SD/MMC driver can distinguish 2440 from 2410 */ 
     35        s3c_device_sdi.name = "s3c2440-sdi"; 
     36 
    3337        return sysdev_register(&s3c2442_sysdev); 
    3438} 
  • arch/arm/Makefile

    a b ifeq ($(CONFIG_CPU_32v6),y) 
    5555arch-$(CONFIG_CPU_32v6K)        :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) 
    5656endif 
    5757arch-$(CONFIG_CPU_32v5)         :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) 
    58 arch-$(CONFIG_CPU_32v4T)        :=-D__LINUX_ARM_ARCH__=4 -march=armv4t 
     58# We can't load armv4t modules, but still need to assemble some armv4t code to be linked in. 
     59arch-$(CONFIG_CPU_32v4T)        :=-D__LINUX_ARM_ARCH__=4 -march=armv4 -Wa,-march=armv4t 
    5960arch-$(CONFIG_CPU_32v4)         :=-D__LINUX_ARM_ARCH__=4 -march=armv4 
    6061arch-$(CONFIG_CPU_32v3)         :=-D__LINUX_ARM_ARCH__=3 -march=armv3 
    6162 
  • new file arch/arm/plat-s3c/include/mach/cpu.h

    - +  
     1/* 
     2 * arch/arm/plat-s3c/include/mach/cpu.h 
     3 * 
     4 *  S3C cpu type detection 
     5 * 
     6 *  Copyright (C) 2008 Samsung Electronics 
     7 *  Kyungmin Park <kyungmin.park@samsung.com> 
     8 * 
     9 * Derived from OMAP cpu.h 
     10 * 
     11 * This program is free software; you can redistribute it and/or modify 
     12 * it under the terms of the GNU General Public License as published by 
     13 * the Free Software Foundation; either version 2 of the License, or 
     14 * (at your option) any later version. 
     15 * 
     16 * This program is distributed in the hope that it will be useful, 
     17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
     19 * GNU General Public License for more details. 
     20 * 
     21 * You should have received a copy of the GNU General Public License 
     22 * along with this program; if not, write to the Free Software 
     23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
     24 */ 
     25 
     26#ifndef __ASM_ARCH_S3C_CPU_H 
     27#define __ASM_ARCH_S3C_CPU_H 
     28 
     29extern unsigned int system_rev; 
     30 
     31#define S3C_SYSTEM_REV_ATAG (system_rev & 0xffff) 
     32#define S3C_SYSTEM_REV_CPU (system_rev & 0xffff0000) 
     33 
     34/* 
     35 * cpu_is_s3c24xx():    True for s3c2400, s3c2410, s3c2440 and so on 
     36 * cpu_is_s3c241x():    True fro s3c2410, s3c2412 
     37 * cpu_is_s3c244x():    True fro s3c2440, s3c2442, s3c2443 
     38 * cpu_is_s3c64xx():    True for s3c6400, s3c6410 
     39 */ 
     40#define GET_S3C_CLASS   ((system_rev >> 24) & 0xff) 
     41 
     42#define IS_S3C_CLASS(class, id)                                         \ 
     43static inline int is_s3c ##class (void)                                 \ 
     44{                                                                       \ 
     45        return (GET_S3C_CLASS == (id)) ? 1 : 0;                         \ 
     46} 
     47 
     48#define GET_S3C_SUBCLASS        ((system_rev >> 20) & 0xfff) 
     49 
     50#define IS_S3C_SUBCLASS(subclass, id)                                   \ 
     51static inline int is_s3c ##subclass (void)                              \ 
     52{                                                                       \ 
     53        return (GET_S3C_SUBCLASS == (id)) ? 1 : 0;                      \ 
     54} 
     55 
     56IS_S3C_CLASS(24xx, 0x24) 
     57IS_S3C_CLASS(64xx, 0x64) 
     58 
     59IS_S3C_SUBCLASS(241x, 0x241) 
     60IS_S3C_SUBCLASS(244x, 0x244) 
     61 
     62#define cpu_is_s3c24xx()                0 
     63#define cpu_is_s3c241x()                0 
     64#define cpu_is_s3c244x()                0 
     65#define cpu_is_s3c64xx()                0 
     66 
     67#if defined(CONFIG_ARCH_S3C2410) 
     68# undef  cpu_is_s3c24xx 
     69# undef  cpu_is_s3c241x 
     70# undef  cpu_is_s3c244x 
     71# define cpu_is_s3c24xx()               is_s3c24xx() 
     72# define cpu_is_s3c241x()               is_s3c241x() 
     73# define cpu_is_s3c244x()               is_s3c244x() 
     74#endif 
     75 
     76#if defined(CONFIG_ARCH_S3C64XX) 
     77# undef  cpu_is_s3c64xx 
     78# define cpu_is_s3c64xx()               is_s3c64xx() 
     79#endif 
     80 
     81/* 
     82 * Macros to detect individual cpu types. 
     83 * cpu_is_s3c2410():    True for s3c2410 
     84 * cpu_is_s3c2440():    True for s3c2440 
     85 * cpu_is_s3c6400():    True for s3c6400 
     86 * cpu_is_s3c6410():    True for s3c6410 
     87 * 
     88 * Exception: 
     89 * Store Revision A to 1 
     90 * s3c2410a -> s3c2411 
     91 * s3c2440a -> s3c2441 
     92 */ 
     93 
     94#define GET_S3C_TYPE    ((system_rev >> 16) & 0xffff) 
     95 
     96#define IS_S3C_TYPE(type, id)                                           \ 
     97static inline int is_s3c ##type (void)                                  \ 
     98{                                                                       \ 
     99        return (GET_S3C_TYPE == (id)) ? 1 : 0;                          \ 
     100} 
     101 
     102IS_S3C_TYPE(2400, 0x2400) 
     103IS_S3C_TYPE(2410, 0x2410) 
     104IS_S3C_TYPE(2410a, 0x2411) 
     105IS_S3C_TYPE(2412, 0x2412) 
     106IS_S3C_TYPE(2440, 0x2440) 
     107IS_S3C_TYPE(2440a, 0x2441) 
     108IS_S3C_TYPE(2442, 0x2442) 
     109IS_S3C_TYPE(2443, 0x2443) 
     110IS_S3C_TYPE(6400, 0x6400) 
     111IS_S3C_TYPE(6410, 0x6410) 
     112 
     113#define cpu_is_s3c2400()                0 
     114#define cpu_is_s3c2410()                0 
     115#define cpu_is_s3c2410a()               0 
     116#define cpu_is_s3c2412()                0 
     117#define cpu_is_s3c2440()                0 
     118#define cpu_is_s3c2440a()               0 
     119#define cpu_is_s3c2442()                0 
     120#define cpu_is_s3c2443()                0 
     121#define cpu_is_s3c6400()                0 
     122#define cpu_is_s3c6410()                0 
     123 
     124#if defined(CONFIG_ARCH_S3C2410) 
     125# undef  cpu_is_s3c2400 
     126# define cpu_is_s3c2400()               is_s3c2400() 
     127#endif 
     128 
     129#if defined(CONFIG_CPU_S3C2410) 
     130# undef  cpu_is_s3c2410 
     131# undef  cpu_is_s3c2410a 
     132# define cpu_is_s3c2410()               is_s3c2410() 
     133# define cpu_is_s3c2410a()              is_s3c2410a() 
     134#endif 
     135 
     136#if defined(CONFIG_CPU_S3C2412) 
     137# undef  cpu_is_s3c2412 
     138# define cpu_is_s3c2412()               is_s3c2412() 
     139#endif 
     140 
     141#if defined(CONFIG_CPU_S3C2440) 
     142# undef  cpu_is_s3c2440 
     143# undef  cpu_is_s3c2440a 
     144# define cpu_is_s3c2440()               is_s3c2440() 
     145# define cpu_is_s3c2440a()              is_s3c2440a() 
     146#endif 
     147 
     148#if defined(CONFIG_CPU_S3C2442) 
     149# undef  cpu_is_s3c2442 
     150# define cpu_is_s3c2442()               is_s3c2442() 
     151#endif 
     152 
     153#if defined(CONFIG_CPU_S3C2443) 
     154# undef  cpu_is_s3c2443 
     155# define cpu_is_s3c2443()               is_s3c2443() 
     156#endif 
     157 
     158#if defined(CONFIG_ARCH_S3C64XX) 
     159# undef  cpu_is_s3c6400 
     160# undef  cpu_is_s3c6410 
     161# define cpu_is_s3c6400()               is_s3c6400() 
     162# define cpu_is_s3c6410()               is_s3c6410() 
     163#endif 
     164 
     165#endif 
  • arch/arm/plat-s3c/include/plat/devs.h

    a b struct s3c24xx_uart_resources { 
    1616        unsigned long            nr_resources; 
    1717}; 
    1818 
     19struct s3c_plat_otg_data { 
     20        int             phyclk; 
     21}; 
     22 
    1923extern struct s3c24xx_uart_resources s3c2410_uart_resources[]; 
    2024extern struct s3c24xx_uart_resources s3c64xx_uart_resources[]; 
    2125 
  • arch/arm/plat-s3c/include/plat/gpio-core.h

    a b  
    2020 * specific code. 
    2121*/ 
    2222 
     23struct s3c_gpio_chip; 
     24 
     25/** 
     26 * struct s3c_gpio_pm - power management (suspend/resume) information 
     27 * @save: Routine to save the state of the GPIO block 
     28 * @resume: Routine to resume the GPIO block. 
     29 */ 
     30struct s3c_gpio_pm { 
     31        void (*save)(struct s3c_gpio_chip *chip); 
     32        void (*resume)(struct s3c_gpio_chip *chip); 
     33}; 
     34 
     35 
    2336struct s3c_gpio_cfg; 
    2437 
    2538/** 
    struct s3c_gpio_cfg; 
    2740 * @chip: The chip structure to be exported via gpiolib. 
    2841 * @base: The base pointer to the gpio configuration registers. 
    2942 * @config: special function and pull-resistor control information. 
     43 * @pm_save: Save information for suspend/resume support. 
    3044 * 
    3145 * This wrapper provides the necessary information for the Samsung 
    3246 * specific gpios being registered with gpiolib. 
    struct s3c_gpio_cfg; 
    3448struct s3c_gpio_chip { 
    3549        struct gpio_chip        chip; 
    3650        struct s3c_gpio_cfg     *config; 
     51        struct s3c_gpio_pm      *pm; 
    3752        void __iomem            *base; 
     53#ifdef CONFIG_PM 
     54        u32                     pm_save[4]; 
     55#endif 
    3856}; 
    3957 
    4058static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc) 
    static inline struct s3c_gpio_chip *s3c_ 
    7593 
    7694static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { } 
    7795#endif 
     96 
     97#ifdef CONFIG_PM 
     98extern struct s3c_gpio_pm s3c_gpio_pm_1bit; 
     99extern struct s3c_gpio_pm s3c_gpio_pm_2bit; 
     100extern struct s3c_gpio_pm s3c_gpio_pm_4bit; 
     101#define __gpio_pm(x) x 
     102#else 
     103#define s3c_gpio_pm_1bit NULL 
     104#define s3c_gpio_pm_2bit NULL 
     105#define s3c_gpio_pm_4bit NULL 
     106#define __gpio_pm(x) NULL 
     107 
     108#endif /* CONFIG_PM */ 
  • arch/arm/plat-s3c/include/plat/map-base.h

    a b  
    3636#define S3C_VA_TIMER    S3C_ADDR(0x00300000)    /* timer block */ 
    3737#define S3C_VA_WATCHDOG S3C_ADDR(0x00400000)    /* watchdog */ 
    3838#define S3C_VA_UART     S3C_ADDR(0x01000000)    /* UART */ 
     39#define S3C_VA_OTG      S3C_ADDR(0x03900000)    /* OTG */ 
     40#define S3C_VA_OTGSFR   S3C_ADDR(0x03a00000)    /* OTGSFR */ 
    3941 
    4042#endif /* __ASM_PLAT_MAP_H */ 
  • arch/arm/plat-s3c/include/plat/nand.h

    a b  
    2121 * partitions    = mtd partition list 
    2222*/ 
    2323 
     24#define S3C2410_NAND_BBT        0x0001 
     25 
    2426struct s3c2410_nand_set { 
    2527        unsigned int            disable_ecc : 1; 
    2628 
    2729        int                     nr_chips; 
    2830        int                     nr_partitions; 
     31        unsigned int            flags; 
    2932        char                    *name; 
    3033        int                     *nr_map; 
    3134        struct mtd_partition    *partitions; 
    struct s3c2410_platform_nand { 
    4447        int                     nr_sets; 
    4548        struct s3c2410_nand_set *sets; 
    4649 
     50        /* force software_ecc at runtime */ 
     51        int     software_ecc; 
     52 
    4753        void                    (*select_chip)(struct s3c2410_nand_set *, 
    4854                                               int chip); 
    4955}; 
  • arch/arm/plat-s3c/include/plat/pm.h

    a b  
    99 * published by the Free Software Foundation. 
    1010*/ 
    1111 
     12#include <linux/sysdev.h> 
     13 
    1214/* s3c_pm_init 
    1315 * 
    1416 * called from board at initialisation time to setup the power 
    extern void (*pm_cpu_sleep)(void); 
    4446 
    4547extern unsigned long s3c_pm_flags; 
    4648 
     49extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */ 
     50 
    4751/* from sleep.S */ 
    4852 
    4953extern int  s3c_cpu_save(unsigned long *saveblk); 
    struct pm_uart_save { 
    8892        u32     ufcon; 
    8993        u32     umcon; 
    9094        u32     ubrdiv; 
     95        u32     udivslot; 
    9196}; 
    9297 
    9398/* helper functions to save/restore lists of registers. */ 
  • arch/arm/plat-s3c/include/plat/sdhci.h

    a b struct mmc_ios; 
    2929 *            is necessary the controllers and/or GPIO blocks require the 
    3030 *            changing of driver-strength and other controls dependant on 
    3131 *            the card and speed of operation. 
     32 * sdhci_host: Pointer kept during init, allows presence change notification 
    3233 * 
    3334 * Initialisation data specific to either the machine or the platform 
    3435 * for the device driver to use or call-back when configuring gpio or 
    struct s3c_sdhci_platdata { 
    4546                            void __iomem *regbase, 
    4647                            struct mmc_ios *ios, 
    4748                            struct mmc_card *card); 
     49        struct sdhci_host * sdhci_host; 
    4850}; 
    4951 
     52extern void sdhci_s3c_force_presence_change(struct platform_device *pdev); 
     53 
    5054/** 
    5155 * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device. 
    5256 * @pd: Platform data to register to device. 
  • arch/arm/plat-s3c/init.c

    a b  
    3131 
    3232static struct cpu_table *cpu; 
    3333 
     34static void __init set_system_rev(unsigned int idcode) 
     35{ 
     36        /* 
     37         * system_rev encoding is as follows 
     38         * system_rev & 0xff000000 -> S3C Class (24xx/64xx) 
     39         * system_rev & 0xfff00000 -> S3C Sub Class (241x/244x) 
     40         * system_rev & 0xffff0000 -> S3C Type (2410/2440/6400/6410) 
     41         * 
     42         * Remaining[15:0] are preserved from the value set by ATAG 
     43         * 
     44         * Exception: 
     45         *  Store Revision A to 1 such as 
     46         *  s3c2410A to s3c2411 
     47         *  s3c2440A to s3c2441 
     48         */ 
     49 
     50        system_rev &= 0xffff; 
     51        system_rev |= (idcode & 0x0ffff000) << 4; 
     52 
     53        if (idcode == 0x32410002 || idcode == 0x32440001) 
     54                system_rev |= (0x1 << 16); 
     55        if (idcode == 0x32440aaa        /* s3c2442 */ 
     56            || idcode == 0x32440aab)    /* s3c2442b */ 
     57                system_rev |= (0x2 << 16); 
     58        if (idcode == 0x0)              /* s3c2400 */ 
     59                system_rev |= (0x2400 << 16); 
     60} 
     61 
    3462static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode, 
    3563                                                struct cpu_table *tab, 
    3664                                                unsigned int count) 
    void __init s3c_init_cpu(unsigned long i 
    5381                panic("Unknown S3C24XX CPU"); 
    5482        } 
    5583 
     84        set_system_rev(idcode); 
     85 
    5686        printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); 
    5787 
    5888        if (cpu->map_io == NULL || cpu->init == NULL) { 
  • arch/arm/plat-s3c/Makefile

    a b obj-y += gpio-config.o 
    2121# PM support 
    2222 
    2323obj-$(CONFIG_PM)                += pm.o 
     24obj-$(CONFIG_PM)                += pm-gpio.o 
    2425obj-$(CONFIG_S3C2410_PM_CHECK)  += pm-check.o 
    2526 
    2627# devices 
  • arch/arm/plat-s3c/pm.c

    a b  
    2121 
    2222#include <asm/cacheflush.h> 
    2323#include <mach/hardware.h> 
     24#include <mach/map.h> 
    2425 
    2526#include <plat/regs-serial.h> 
    2627#include <mach/regs-clock.h> 
    27 #include <mach/regs-gpio.h> 
    28 #include <mach/regs-mem.h> 
    2928#include <mach/regs-irq.h> 
    3029#include <asm/irq.h> 
    3130 
    static inline void s3c_pm_debug_init(voi 
    7069 
    7170/* Save the UART configurations if we are configured for debug. */ 
    7271 
     72unsigned char pm_uart_udivslot; 
     73 
    7374#ifdef CONFIG_S3C2410_PM_DEBUG 
    7475 
    7576struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS]; 
    static void s3c_pm_save_uart(unsigned in 
    8384        save->ufcon = __raw_readl(regs + S3C2410_UFCON); 
    8485        save->umcon = __raw_readl(regs + S3C2410_UMCON); 
    8586        save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV); 
     87 
     88        if (pm_uart_udivslot) 
     89                save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT); 
     90 
     91        S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n", 
     92                  uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv); 
    8693} 
    8794 
    8895static void s3c_pm_save_uarts(void) 
    static void s3c_pm_restore_uart(unsigned 
    98105{ 
    99106        void __iomem *regs = S3C_VA_UARTx(uart); 
    100107 
     108        s3c_pm_arch_update_uart(regs, save); 
     109 
    101110        __raw_writel(save->ulcon, regs + S3C2410_ULCON); 
    102111        __raw_writel(save->ucon,  regs + S3C2410_UCON); 
    103112        __raw_writel(save->ufcon, regs + S3C2410_UFCON); 
    104113        __raw_writel(save->umcon, regs + S3C2410_UMCON); 
    105114        __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV); 
     115 
     116        if (pm_uart_udivslot) 
     117                __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT); 
    106118} 
    107119 
    108120static void s3c_pm_restore_uarts(void) 
    static int s3c_pm_enter(suspend_state_t  
    289301 
    290302        s3c_pm_arch_stop_clocks(); 
    291303 
    292         /* s3c_cpu_save will also act as our return point from when 
    293          * we resume as it saves its own register state and restores it 
    294          * during the resume.  */ 
    295  
    296         s3c_cpu_save(regs_save); 
     304        /* s3c2410_cpu_save will also act as our return point from when 
     305         * we resume as it saves its own register state, so use the return 
     306         * code to differentiate return from save and return from sleep */ 
     307 
     308        if (s3c_cpu_save(regs_save) == 0) { 
     309                flush_cache_all(); 
     310                pm_cpu_sleep(); 
     311        } 
    297312 
    298313        /* restore the cpu state using the kernel's cpu init code. */ 
    299314 
  • new file arch/arm/plat-s3c/pm-gpio.c

    - +  
     1/* linux/arch/arm/plat-s3c/pm-gpio.c 
     2 * 
     3 * Copyright 2008 Openmoko, Inc. 
     4 * Copyright 2008 Simtec Electronics 
     5 *      Ben Dooks <ben@simtec.co.uk> 
     6 *      http://armlinux.simtec.co.uk/ 
     7 * 
     8 * S3C series GPIO PM code 
     9 * 
     10 * This program is free software; you can redistribute it and/or modify 
     11 * it under the terms of the GNU General Public License version 2 as 
     12 * published by the Free Software Foundation. 
     13*/ 
     14 
     15#include <linux/kernel.h> 
     16#include <linux/init.h> 
     17#include <linux/io.h> 
     18#include <linux/gpio.h> 
     19 
     20#include <mach/gpio-core.h> 
     21#include <plat/pm.h> 
     22 
     23/* PM GPIO helpers */ 
     24 
     25#define OFFS_CON        (0x00) 
     26#define OFFS_DAT        (0X04) 
     27#define OFFS_UP         (0X08) 
     28 
     29static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip) 
     30{ 
     31        chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON); 
     32        chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT); 
     33} 
     34 
     35static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip) 
     36{ 
     37        void __iomem *base = chip->base; 
     38        u32 old_gpcon = __raw_readl(base + OFFS_CON); 
     39        u32 old_gpdat = __raw_readl(base + OFFS_DAT); 
     40        u32 gps_gpcon = chip->pm_save[0]; 
     41        u32 gps_gpdat = chip->pm_save[1]; 
     42        u32 gpcon; 
     43 
     44        /* GPACON only has one bit per control / data and no PULLUPs. 
     45         * GPACON[x] = 0 => Output, 1 => SFN */ 
     46 
     47        /* first set all SFN bits to SFN */ 
     48 
     49        gpcon = old_gpcon | gps_gpcon; 
     50        __raw_writel(gpcon, base + OFFS_CON); 
     51 
     52        /* now set all the other bits */ 
     53 
     54        __raw_writel(gps_gpdat, base + OFFS_DAT); 
     55        __raw_writel(gps_gpcon, base + OFFS_CON); 
     56 
     57        S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n", 
     58                  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat); 
     59} 
     60 
     61struct s3c_gpio_pm s3c_gpio_pm_1bit = { 
     62        .save   = s3c_gpio_pm_1bit_save, 
     63        .resume = s3c_gpio_pm_1bit_resume, 
     64}; 
     65 
     66static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip) 
     67{ 
     68        chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON); 
     69        chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT); 
     70        chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP); 
     71} 
     72 
     73/* Test whether the given masked+shifted bits of an GPIO configuration 
     74 * are one of the SFN (special function) modes. */ 
     75 
     76static inline int is_sfn(unsigned long con) 
     77{ 
     78        return con >= 2; 
     79} 
     80 
     81/* Test if the given masked+shifted GPIO configuration is an input */ 
     82 
     83static inline int is_in(unsigned long con) 
     84{ 
     85        return con == 0; 
     86} 
     87 
     88/* Test if the given masked+shifted GPIO configuration is an output */ 
     89 
     90static inline int is_out(unsigned long con) 
     91{ 
     92        return con == 1; 
     93} 
     94 
     95/** 
     96 * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank 
     97 * @chip: The chip information to resume. 
     98 * 
     99 * Restore one of the GPIO banks that was saved during suspend. This is 
     100 * not as simple as once thought, due to the possibility of glitches 
     101 * from the order that the CON and DAT registers are set in. 
     102 * 
     103 * The three states the pin can be are {IN,OUT,SFN} which gives us 9 
     104 * combinations of changes to check. Three of these, if the pin stays 
     105 * in the same configuration can be discounted. This leaves us with 
     106 * the following: 
     107 * 
     108 * { IN => OUT }  Change DAT first 
     109 * { IN => SFN }  Change CON first 
     110 * { OUT => SFN } Change CON first, so new data will not glitch 
     111 * { OUT => IN }  Change CON first, so new data will not glitch 
     112 * { SFN => IN }  Change CON first 
     113 * { SFN => OUT } Change DAT first, so new data will not glitch [1] 
     114 * 
     115 * We do not currently deal with the UP registers as these control 
     116 * weak resistors, so a small delay in change should not need to bring 
     117 * these into the calculations. 
     118 * 
     119 * [1] this assumes that writing to a pin DAT whilst in SFN will set the 
     120 *     state for when it is next output. 
     121 */ 
     122static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip) 
     123{ 
     124        void __iomem *base = chip->base; 
     125        u32 old_gpcon = __raw_readl(base + OFFS_CON); 
     126        u32 old_gpdat = __raw_readl(base + OFFS_DAT); 
     127        u32 gps_gpcon = chip->pm_save[0]; 
     128        u32 gps_gpdat = chip->pm_save[1]; 
     129        u32 gpcon, old, new, mask; 
     130        u32 change_mask = 0x0; 
     131        int nr; 
     132 
     133        /* restore GPIO pull-up settings */ 
     134        __raw_writel(chip->pm_save[2], base + OFFS_UP); 
     135 
     136        /* Create a change_mask of all the items that need to have 
     137         * their CON value changed before their DAT value, so that 
     138         * we minimise the work between the two settings. 
     139         */ 
     140 
     141        for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) { 
     142                old = (old_gpcon & mask) >> nr; 
     143                new = (gps_gpcon & mask) >> nr; 
     144 
     145                /* If there is no change, then skip */ 
     146 
     147                if (old == new) 
     148                        continue; 
     149 
     150                /* If both are special function, then skip */ 
     151 
     152                if (is_sfn(old) && is_sfn(new)) 
     153                        continue; 
     154 
     155                /* Change is IN => OUT, do not change now */ 
     156 
     157                if (is_in(old) && is_out(new)) 
     158                        continue; 
     159 
     160                /* Change is SFN => OUT, do not change now */ 
     161 
     162                if (is_sfn(old) && is_out(new)) 
     163                        continue; 
     164 
     165                /* We should now be at the case of IN=>SFN, 
     166                 * OUT=>SFN, OUT=>IN, SFN=>IN. */ 
     167 
     168                change_mask |= mask; 
     169        } 
     170 
     171 
     172        /* Write the new CON settings */ 
     173 
     174        gpcon = old_gpcon & ~change_mask; 
     175        gpcon |= gps_gpcon & change_mask; 
     176 
     177        __raw_writel(gpcon, base + OFFS_CON); 
     178 
     179        /* Now change any items that require DAT,CON */ 
     180 
     181        __raw_writel(gps_gpdat, base + OFFS_DAT); 
     182        __raw_writel(gps_gpcon, base + OFFS_CON); 
     183 
     184        S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n", 
     185                  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat); 
     186} 
     187 
     188struct s3c_gpio_pm s3c_gpio_pm_2bit = { 
     189        .save   = s3c_gpio_pm_2bit_save, 
     190        .resume = s3c_gpio_pm_2bit_resume, 
     191}; 
     192 
     193#ifdef CONFIG_ARCH_S3C64XX 
     194static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip) 
     195{ 
     196        chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON); 
     197        chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT); 
     198        chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP); 
     199 
     200        if (chip->chip.ngpio > 8) 
     201                chip->pm_save[0] = __raw_readl(chip->base - 4); 
     202} 
     203 
     204static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon) 
     205{ 
     206        u32 old, new, mask; 
     207        u32 change_mask = 0x0; 
     208        int nr; 
     209 
     210        for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) { 
     211                old = (old_gpcon & mask) >> nr; 
     212                new = (gps_gpcon & mask) >> nr; 
     213 
     214                /* If there is no change, then skip */ 
     215 
     216                if (old == new) 
     217                        continue; 
     218 
     219                /* If both are special function, then skip */ 
     220 
     221                if (is_sfn(old) && is_sfn(new)) 
     222                        continue; 
     223 
     224                /* Change is IN => OUT, do not change now */ 
     225 
     226                if (is_in(old) && is_out(new)) 
     227                        continue; 
     228 
     229                /* Change is SFN => OUT, do not change now */ 
     230 
     231                if (is_sfn(old) && is_out(new)) 
     232                        continue; 
     233 
     234                /* We should now be at the case of IN=>SFN, 
     235                 * OUT=>SFN, OUT=>IN, SFN=>IN. */ 
     236 
     237                change_mask |= mask; 
     238        } 
     239 
     240        return change_mask; 
     241} 
     242 
     243static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index) 
     244{ 
     245        void __iomem *con = chip->base + (index * 4); 
     246        u32 old_gpcon = __raw_readl(con); 
     247        u32 gps_gpcon = chip->pm_save[index + 1]; 
     248        u32 gpcon, mask; 
     249 
     250        mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon); 
     251 
     252        gpcon = old_gpcon & ~mask; 
     253        gpcon |= gps_gpcon & mask; 
     254 
     255        __raw_writel(gpcon, con); 
     256} 
     257 
     258static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip) 
     259{ 
     260        void __iomem *base = chip->base; 
     261        u32 old_gpcon[2]; 
     262        u32 old_gpdat = __raw_readl(base + OFFS_DAT); 
     263        u32 gps_gpdat = chip->pm_save[2]; 
     264 
     265        /* First, modify the CON settings */ 
     266 
     267        old_gpcon[0] = 0; 
     268        old_gpcon[1] = __raw_readl(base + OFFS_CON); 
     269 
     270        s3c_gpio_pm_4bit_con(chip, 0); 
     271        if (chip->chip.ngpio > 8) { 
     272                old_gpcon[0] = __raw_readl(base - 4); 
     273                s3c_gpio_pm_4bit_con(chip, -1); 
     274        } 
     275 
     276        /* Now change the configurations that require DAT,CON */ 
     277 
     278        __raw_writel(chip->pm_save[2], base + OFFS_DAT); 
     279        __raw_writel(chip->pm_save[1], base + OFFS_CON); 
     280        if (chip->chip.ngpio > 8) 
     281                __raw_writel(chip->pm_save[0], base - 4); 
     282 
     283        __raw_writel(chip->pm_save[2], base + OFFS_DAT); 
     284        __raw_writel(chip->pm_save[3], base + OFFS_UP); 
     285 
     286        if (chip->chip.ngpio > 8) { 
     287                S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n", 
     288                          chip->chip.label, old_gpcon[0], old_gpcon[1], 
     289                          __raw_readl(base - 4), 
     290                          __raw_readl(base + OFFS_CON), 
     291                          old_gpdat, gps_gpdat); 
     292        } else 
     293                S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n", 
     294                          chip->chip.label, old_gpcon[1], 
     295                          __raw_readl(base + OFFS_CON), 
     296                          old_gpdat, gps_gpdat); 
     297} 
     298 
     299struct s3c_gpio_pm s3c_gpio_pm_4bit = { 
     300        .save   = s3c_gpio_pm_4bit_save, 
     301        .resume = s3c_gpio_pm_4bit_resume, 
     302}; 
     303#endif /* CONFIG_ARCH_S3C64XX */ 
     304 
     305/** 
     306 * s3c_pm_save_gpio() - save gpio chip data for suspend 
     307 * @ourchip: The chip for suspend. 
     308 */ 
     309static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip) 
     310{ 
     311        struct s3c_gpio_pm *pm = ourchip->pm; 
     312 
     313        if (pm == NULL || pm->save == NULL) 
     314                S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label); 
     315        else 
     316                pm->save(ourchip); 
     317} 
     318 
     319/** 
     320 * s3c_pm_save_gpios() - Save the state of the GPIO banks. 
     321 * 
     322 * For all the GPIO banks, save the state of each one ready for going 
     323 * into a suspend mode. 
     324 */ 
     325void s3c_pm_save_gpios(void) 
     326{ 
     327        struct s3c_gpio_chip *ourchip; 
     328        unsigned int gpio_nr; 
     329 
     330        for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) { 
     331                ourchip = s3c_gpiolib_getchip(gpio_nr); 
     332                if (!ourchip) 
     333                        continue; 
     334 
     335                s3c_pm_save_gpio(ourchip); 
     336 
     337                S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n", 
     338                          ourchip->chip.label, 
     339                          ourchip->pm_save[0], 
     340                          ourchip->pm_save[1], 
     341                          ourchip->pm_save[2], 
     342                          ourchip->pm_save[3]); 
     343 
     344                gpio_nr += ourchip->chip.ngpio; 
     345                gpio_nr += CONFIG_S3C_GPIO_SPACE; 
     346        } 
     347} 
     348 
     349/** 
     350 * s3c_pm_resume_gpio() - restore gpio chip data after suspend 
     351 * @ourchip: The suspended chip. 
     352 */ 
     353static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip) 
     354{ 
     355        struct s3c_gpio_pm *pm = ourchip->pm; 
     356 
     357        if (pm == NULL || pm->resume == NULL) 
     358                S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label); 
     359        else 
     360                pm->resume(ourchip); 
     361} 
     362 
     363void s3c_pm_restore_gpios(void) 
     364{ 
     365        struct s3c_gpio_chip *ourchip; 
     366        unsigned int gpio_nr; 
     367 
     368        for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) { 
     369                ourchip = s3c_gpiolib_getchip(gpio_nr); 
     370                if (!ourchip) 
     371                        continue; 
     372 
     373                s3c_pm_resume_gpio(ourchip); 
     374 
     375                gpio_nr += ourchip->chip.ngpio; 
     376                gpio_nr += CONFIG_S3C_GPIO_SPACE; 
     377        } 
     378} 
  • arch/arm/plat-s3c24xx/clock-dclk.c

    a b  
    1818 
    1919#include <mach/regs-clock.h> 
    2020#include <mach/regs-gpio.h> 
     21#include <mach/hardware.h> 
    2122 
    2223#include <plat/clock.h> 
    2324#include <plat/cpu.h> 
  • arch/arm/plat-s3c24xx/cpu.c

    a b static const char name_s3c2410[] = "S3C 
    6161static const char name_s3c2412[]  = "S3C2412"; 
    6262static const char name_s3c2440[]  = "S3C2440"; 
    6363static const char name_s3c2442[]  = "S3C2442"; 
     64static const char name_s3c2442b[]  = "S3C2442B"; 
    6465static const char name_s3c2443[]  = "S3C2443"; 
    6566static const char name_s3c2410a[] = "S3C2410A"; 
    6667static const char name_s3c2440a[] = "S3C2440A"; 
    static struct cpu_table cpu_ids[] __init 
    112113                .name           = name_s3c2442 
    113114        }, 
    114115        { 
     116                .idcode         = 0x32440aab, 
     117                .idmask         = 0xffffffff, 
     118                .map_io         = s3c244x_map_io, 
     119                .init_clocks    = s3c244x_init_clocks, 
     120                .init_uarts     = s3c244x_init_uarts, 
     121                .init           = s3c2442_init, 
     122                .name           = name_s3c2442b 
     123        }, 
     124        { 
    115125                .idcode         = 0x32412001, 
    116126                .idmask         = 0xffffffff, 
    117127                .map_io         = s3c2412_map_io, 
  • arch/arm/plat-s3c24xx/gpiolib.c

    a b  
    1919#include <linux/io.h> 
    2020#include <linux/gpio.h> 
    2121 
    22 #include <mach/gpio-core.h> 
     22#include <plat/gpio-core.h> 
    2323#include <mach/hardware.h> 
    2424#include <asm/irq.h> 
     25#include <plat/pm.h> 
    2526 
    2627#include <mach/regs-gpio.h> 
    2728 
    static int s3c24xx_gpiolib_bankg_toirq(s 
    7879struct s3c_gpio_chip s3c24xx_gpios[] = { 
    7980        [0] = { 
    8081                .base   = S3C24XX_GPIO_BASE(S3C2410_GPA0), 
     82                .pm     = __gpio_pm(&s3c_gpio_pm_1bit), 
    8183                .chip   = { 
    8284                        .base                   = S3C2410_GPA0, 
    8385                        .owner                  = THIS_MODULE, 
    struct s3c_gpio_chip s3c24xx_gpios[] = { 
    8991        }, 
    9092        [1] = { 
    9193                .base   = S3C24XX_GPIO_BASE(S3C2410_GPB0), 
     94                .pm     = __gpio_pm(&s3c_gpio_pm_2bit), 
    9295                .chip   = { 
    9396                        .base                   = S3C2410_GPB0, 
    9497                        .owner                  = THIS_MODULE, 
    struct s3c_gpio_chip s3c24xx_gpios[] = { 
    98101        }, 
    99102        [2] = { 
    100103                .base   = S3C24XX_GPIO_BASE(S3C2410_GPC0), 
     104                .pm     = __gpio_pm(&s3c_gpio_pm_2bit), 
    101105                .chip   = { 
    102106                        .base                   = S3C2410_GPC0, 
    103107                        .owner                  = THIS_MODULE, 
    struct s3c_gpio_chip s3c24xx_gpios[] = { 
    107111        }, 
    108112        [3] = { 
    109113                .base   = S3C24XX_GPIO_BASE(S3C2410_GPD0), 
     114                .pm     = __gpio_pm(&s3c_gpio_pm_2bit), 
    110115                .chip   = { 
    111116                        .base                   = S3C2410_GPD0, 
    112117                        .owner                  = THIS_MODULE, 
    struct s3c_gpio_chip s3c24xx_gpios[] = { 
    116121        }, 
    117122        [4] = { 
    118123                .base   = S3C24XX_GPIO_BASE(S3C2410_GPE0), 
     124                .pm     = __gpio_pm(&s3c_gpio_pm_2bit), 
    119125                .chip   = { 
    120126                        .base                   = S3C2410_GPE0, 
    121127                        .label                  = "GPIOE", 
    struct s3c_gpio_chip s3c24xx_gpios[] = { 
    125131        }, 
    126132        [5] = { 
    127133                .base   = S3C24XX_GPIO_BASE(S3C2410_GPF0), 
     134                .pm     = __gpio_pm(&s3c_gpio_pm_2bit), 
    128135                .chip   = { 
    129136                        .base                   = S3C2410_GPF0, 
    130137                        .owner                  = THIS_MODULE, 
    struct s3c_gpio_chip s3c24xx_gpios[] = { 
    135142        }, 
    136143        [6] = { 
    137144                .base   = S3C24XX_GPIO_BASE(S3C2410_GPG0), 
     145                .pm     = __gpio_pm(&s3c_gpio_pm_2bit), 
    138146                .chip   = { 
    139147                        .base                   = S3C2410_GPG0, 
    140148                        .owner                  = THIS_MODULE, 
    141149                        .label                  = "GPIOG", 
    142                         .ngpio                  = 10, 
    143150                        .to_irq                 = s3c24xx_gpiolib_bankg_toirq, 
     151                        .ngpio                  = 16, 
     152                }, 
     153        }, 
     154        [7] = { 
     155                .base   = S3C24XX_GPIO_BASE(S3C2410_GPH0), 
     156                .pm     = __gpio_pm(&s3c_gpio_pm_2bit), 
     157                .chip   = { 
     158                        .base                   = S3C2410_GPH0, 
     159                        .owner                  = THIS_MODULE, 
     160                        .label                  = "GPIOH", 
     161                        .ngpio                  = 11, 
    144162                }, 
    145163        }, 
    146164}; 
  • arch/arm/plat-s3c24xx/include/plat/pm-core.h

    a b static inline void s3c_pm_arch_show_resu 
    5757        s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND), 
    5858                                s3c_irqwake_eintmask); 
    5959} 
     60 
     61static inline void s3c_pm_arch_update_uart(void __iomem *regs, 
     62                                           struct pm_uart_save *save) 
     63{ 
     64} 
  • arch/arm/plat-s3c24xx/irq-pm.c

    a b  
    1515#include <linux/module.h> 
    1616#include <linux/interrupt.h> 
    1717#include <linux/sysdev.h> 
     18#include <linux/irq.h> 
    1819 
    1920#include <plat/cpu.h> 
    2021#include <plat/pm.h> 
    int s3c24xx_irq_suspend(struct sys_devic 
    8081 
    8182int s3c24xx_irq_resume(struct sys_device *dev) 
    8283{ 
    83         unsigned int i; 
     84        unsigned int i, irq; 
     85        unsigned long eintpnd; 
     86        struct irq_desc *desc; 
    8487 
    8588        for (i = 0; i < ARRAY_SIZE(save_extint); i++) 
    8689                __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4)); 
    int s3c24xx_irq_resume(struct sys_device 
    9194        s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); 
    9295        __raw_writel(save_eintmask, S3C24XX_EINTMASK); 
    9396 
     97        /* 
     98         * ACK those interrupts which are now masked and pending. 
     99         * Level interrupts if not ACKed here, create an interrupt storm 
     100         * because they are not handled at all. 
     101         */ 
     102 
     103        eintpnd = __raw_readl(S3C24XX_EINTPEND); 
     104 
     105        eintpnd &= save_eintmask; 
     106        eintpnd &= ~0xff;       /* ignore lower irqs */ 
     107 
     108        while (eintpnd) { 
     109                irq = __ffs(eintpnd); 
     110                eintpnd &= ~(1 << irq); 
     111 
     112                irq += (IRQ_EINT4 - 4); 
     113                desc = irq_to_desc(irq); 
     114                desc->chip->ack(irq); 
     115        } 
     116 
    94117        return 0; 
    95118} 
  • arch/arm/plat-s3c24xx/pm.c

    a b  
    3939#include <mach/regs-gpio.h> 
    4040#include <mach/regs-mem.h> 
    4141#include <mach/regs-irq.h> 
     42#include <mach/hardware.h> 
    4243 
    4344#include <asm/mach/time.h> 
    4445 
    static struct sleep_save core_save[] = { 
    7576        SAVE_ITEM(S3C2410_CLKSLOW), 
    7677}; 
    7778 
    78 static struct gpio_sleep { 
    79         void __iomem    *base; 
    80         unsigned int     gpcon; 
    81         unsigned int     gpdat; 
    82         unsigned int     gpup; 
    83 } gpio_save[] = { 
    84         [0] = { 
    85                 .base   = S3C2410_GPACON, 
    86         }, 
    87         [1] = { 
    88                 .base   = S3C2410_GPBCON, 
    89         }, 
    90         [2] = { 
    91                 .base   = S3C2410_GPCCON, 
    92         }, 
    93         [3] = { 
    94                 .base   = S3C2410_GPDCON, 
    95         }, 
    96         [4] = { 
    97                 .base   = S3C2410_GPECON, 
    98         }, 
    99         [5] = { 
    100                 .base   = S3C2410_GPFCON, 
    101         }, 
    102         [6] = { 
    103                 .base   = S3C2410_GPGCON, 
    104         }, 
    105         [7] = { 
    106                 .base   = S3C2410_GPHCON, 
    107         }, 
    108 }; 
    109  
    11079static struct sleep_save misc_save[] = { 
    11180        SAVE_ITEM(S3C2410_DCLKCON), 
    11281}; 
    11382 
    114  
    11583/* s3c_pm_check_resume_pin 
    11684 * 
    11785 * check to see if the pin is configured correctly for sleep mode, and 
    void s3c_pm_configure_extint(void) 
    165133        } 
    166134} 
    167135 
    168 /* offsets for CON/DAT/UP registers */ 
    169  
    170 #define OFFS_CON        (S3C2410_GPACON - S3C2410_GPACON) 
    171 #define OFFS_DAT        (S3C2410_GPADAT - S3C2410_GPACON) 
    172 #define OFFS_UP         (S3C2410_GPBUP  - S3C2410_GPBCON) 
    173  
    174 /* s3c_pm_save_gpios() 
    175  * 
    176  * Save the state of the GPIOs 
    177  */ 
    178  
    179 void s3c_pm_save_gpios(void) 
    180 { 
    181         struct gpio_sleep *gps = gpio_save; 
    182         unsigned int gpio; 
    183  
    184         for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) { 
    185                 void __iomem *base = gps->base; 
    186  
    187                 gps->gpcon = __raw_readl(base + OFFS_CON); 
    188                 gps->gpdat = __raw_readl(base + OFFS_DAT); 
    189  
    190                 if (gpio > 0) 
    191                         gps->gpup = __raw_readl(base + OFFS_UP); 
    192  
    193         } 
    194 } 
    195  
    196 /* Test whether the given masked+shifted bits of an GPIO configuration 
    197  * are one of the SFN (special function) modes. */ 
    198  
    199 static inline int is_sfn(unsigned long con) 
    200 { 
    201         return (con == 2 || con == 3); 
    202 } 
    203  
    204 /* Test if the given masked+shifted GPIO configuration is an input */ 
    205  
    206 static inline int is_in(unsigned long con) 
    207 { 
    208         return con == 0; 
    209 } 
    210  
    211 /* Test if the given masked+shifted GPIO configuration is an output */ 
    212  
    213 static inline int is_out(unsigned long con) 
    214 { 
    215         return con == 1; 
    216 } 
    217  
    218 /** 
    219  * s3c2410_pm_restore_gpio() - restore the given GPIO bank 
    220  * @index: The number of the GPIO bank being resumed. 
    221  * @gps: The sleep confgiuration for the bank. 
    222  * 
    223  * Restore one of the GPIO banks that was saved during suspend. This is 
    224  * not as simple as once thought, due to the possibility of glitches 
    225  * from the order that the CON and DAT registers are set in. 
    226  * 
    227  * The three states the pin can be are {IN,OUT,SFN} which gives us 9 
    228  * combinations of changes to check. Three of these, if the pin stays 
    229  * in the same configuration can be discounted. This leaves us with 
    230  * the following: 
    231  * 
    232  * { IN => OUT }  Change DAT first 
    233  * { IN => SFN }  Change CON first 
    234  * { OUT => SFN } Change CON first, so new data will not glitch 
    235  * { OUT => IN }  Change CON first, so new data will not glitch 
    236  * { SFN => IN }  Change CON first 
    237  * { SFN => OUT } Change DAT first, so new data will not glitch [1] 
    238  * 
    239  * We do not currently deal with the UP registers as these control 
    240  * weak resistors, so a small delay in change should not need to bring 
    241  * these into the calculations. 
    242  * 
    243  * [1] this assumes that writing to a pin DAT whilst in SFN will set the 
    244  *     state for when it is next output. 
    245  */ 
    246  
    247 static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps) 
    248 { 
    249         void __iomem *base = gps->base; 
    250         unsigned long gps_gpcon = gps->gpcon; 
    251         unsigned long gps_gpdat = gps->gpdat; 
    252         unsigned long old_gpcon; 
    253         unsigned long old_gpdat; 
    254         unsigned long old_gpup = 0x0; 
    255         unsigned long gpcon; 
    256         int nr; 
    257  
    258         old_gpcon = __raw_readl(base + OFFS_CON); 
    259         old_gpdat = __raw_readl(base + OFFS_DAT); 
    260  
    261         if (base == S3C2410_GPACON) { 
    262                 /* GPACON only has one bit per control / data and no PULLUPs. 
    263                  * GPACON[x] = 0 => Output, 1 => SFN */ 
    264  
    265                 /* first set all SFN bits to SFN */ 
    266  
    267                 gpcon = old_gpcon | gps->gpcon; 
    268                 __raw_writel(gpcon, base + OFFS_CON); 
    269  
    270                 /* now set all the other bits */ 
    271  
    272                 __raw_writel(gps_gpdat, base + OFFS_DAT); 
    273                 __raw_writel(gps_gpcon, base + OFFS_CON); 
    274         } else { 
    275                 unsigned long old, new, mask; 
    276                 unsigned long change_mask = 0x0; 
    277  
    278                 old_gpup = __raw_readl(base + OFFS_UP); 
    279  
    280                 /* Create a change_mask of all the items that need to have 
    281                  * their CON value changed before their DAT value, so that 
    282                  * we minimise the work between the two settings. 
    283                  */ 
    284  
    285                 for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) { 
    286                         old = (old_gpcon & mask) >> nr; 
    287                         new = (gps_gpcon & mask) >> nr; 
    288  
    289                         /* If there is no change, then skip */ 
    290  
    291                         if (old == new) 
    292                                 continue; 
    293  
    294                         /* If both are special function, then skip */ 
    295  
    296                         if (is_sfn(old) && is_sfn(new)) 
    297                                 continue; 
    298  
    299                         /* Change is IN => OUT, do not change now */ 
    300  
    301                         if (is_in(old) && is_out(new)) 
    302                                 continue; 
    303  
    304                         /* Change is SFN => OUT, do not change now */ 
    305  
    306                         if (is_sfn(old) && is_out(new)) 
    307                                 continue; 
    308  
    309                         /* We should now be at the case of IN=>SFN, 
    310                          * OUT=>SFN, OUT=>IN, SFN=>IN. */ 
    311  
    312                         change_mask |= mask; 
    313                 } 
    314  
    315                 /* Write the new CON settings */ 
    316  
    317                 gpcon = old_gpcon & ~change_mask; 
    318                 gpcon |= gps_gpcon & change_mask; 
    319  
    320                 __raw_writel(gpcon, base + OFFS_CON); 
    321  
    322                 /* Now change any items that require DAT,CON */ 
    323  
    324                 __raw_writel(gps_gpdat, base + OFFS_DAT); 
    325                 __raw_writel(gps_gpcon, base + OFFS_CON); 
    326                 __raw_writel(gps->gpup, base + OFFS_UP); 
    327         } 
    328  
    329         S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n", 
    330                   index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat); 
    331 } 
    332  
    333  
    334 /** s3c2410_pm_restore_gpios() 
    335  * 
    336  * Restore the state of the GPIOs 
    337  */ 
    338  
    339 void s3c_pm_restore_gpios(void) 
    340 { 
    341         struct gpio_sleep *gps = gpio_save; 
    342         int gpio; 
    343  
    344         for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) { 
    345                 s3c2410_pm_restore_gpio(gpio, gps); 
    346         } 
    347 } 
    348136 
    349137void s3c_pm_restore_core(void) 
    350138{ 
  • drivers/mmc/host/Kconfig

    a b config MMC_SDHCI 
    3737 
    3838          If unsure, say N. 
    3939 
    40 config MMC_SDHCI_IO_ACCESSORS 
    41         bool 
    42         depends on MMC_SDHCI 
    43         help 
    44           This is silent Kconfig symbol that is selected by the drivers that 
    45           need to overwrite SDHCI IO memory accessors. 
    46  
    4740config MMC_SDHCI_PCI 
    4841        tristate "SDHCI support on PCI bus" 
    4942        depends on MMC_SDHCI && PCI 
    config MMC_SDHCI_PCI 
    5548 
    5649          If unsure, say N. 
    5750 
     51config MMC_SDHCI_S3C 
     52        tristate "SDHCI support on Samsung S3C SoC" 
     53        depends on MMC_SDHCI && PLAT_S3C24XX 
     54        help 
     55          This selects the Secure Digital Host Controller Interface (SDHCI) 
     56          often referrered to as the HSMMC block in some of the Samsung S3C 
     57          range of SoC. 
     58 
     59          If you have a controller with this interface, say Y or M here. 
     60 
     61          If unsure, say N. 
     62 
    5863config MMC_RICOH_MMC 
    5964        tristate "Ricoh MMC Controller Disabler  (EXPERIMENTAL)" 
    6065        depends on MMC_SDHCI_PCI 
    config MMC_RICOH_MMC 
    7277 
    7378          If unsure, say Y. 
    7479 
    75 config MMC_SDHCI_OF 
    76         tristate "SDHCI support on OpenFirmware platforms" 
    77         depends on MMC_SDHCI && PPC_OF 
    78         select MMC_SDHCI_IO_ACCESSORS 
    79         help 
    80           This selects the OF support for Secure Digital Host Controller 
    81           Interfaces. So far, only the Freescale eSDHC controller is known 
    82           to exist on OF platforms. 
    83  
    84           If unsure, say N. 
    85  
    8680config MMC_OMAP 
    8781        tristate "TI OMAP Multimedia Card Interface support" 
    8882        depends on ARCH_OMAP 
    config MMC_IMX 
    163157 
    164158          If unsure, say N. 
    165159 
    166 config MMC_MXC 
    167         tristate "Freescale i.MX2/3 Multimedia Card Interface support" 
    168         depends on ARCH_MXC 
    169         help 
    170           This selects the Freescale i.MX2/3 Multimedia card Interface. 
    171           If you have a i.MX platform with a Multimedia Card slot, 
    172           say Y or M here. 
    173  
    174           If unsure, say N. 
    175  
    176160config MMC_TIFM_SD 
    177161        tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)" 
    178162        depends on EXPERIMENTAL && PCI 
  • drivers/mmc/host/Makefile

    a b endif 
    99obj-$(CONFIG_MMC_ARMMMCI)       += mmci.o 
    1010obj-$(CONFIG_MMC_PXA)           += pxamci.o 
    1111obj-$(CONFIG_MMC_IMX)           += imxmmc.o 
    12 obj-$(CONFIG_MMC_MXC)           += mxcmmc.o 
    1312obj-$(CONFIG_MMC_SDHCI)         += sdhci.o 
    1413obj-$(CONFIG_MMC_SDHCI_PCI)     += sdhci-pci.o 
     14obj-$(CONFIG_MMC_SDHCI_S3C)     += sdhci-s3c.o 
    1515obj-$(CONFIG_MMC_RICOH_MMC)     += ricoh_mmc.o 
    16 obj-$(CONFIG_MMC_SDHCI_OF)      += sdhci-of.o 
    1716obj-$(CONFIG_MMC_WBSD)          += wbsd.o 
    1817obj-$(CONFIG_MMC_AU1X)          += au1xmmc.o 
    1918obj-$(CONFIG_MMC_OMAP)          += omap.o 
    obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc. 
    2120obj-$(CONFIG_MMC_AT91)          += at91_mci.o 
    2221obj-$(CONFIG_MMC_ATMELMCI)      += atmel-mci.o 
    2322obj-$(CONFIG_MMC_TIFM_SD)       += tifm_sd.o 
    24 obj-$(CONFIG_MMC_MVSDIO)        += mvsdio.o 
    2523obj-$(CONFIG_MMC_SPI)           += mmc_spi.o 
    2624ifeq ($(CONFIG_OF),y) 
    2725obj-$(CONFIG_MMC_SPI)           += of_mmc_spi.o 
  • drivers/mmc/host/s3cmci.c

    a b  
    22 *  linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver 
    33 * 
    44 *  Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de> 
     5 *  Copyright (C) 2007 Harald Welte <laforge@gnumonks.org> 
    56 * 
    67 * Current driver maintained by Ben Dooks and Simtec Electronics 
    78 *  Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.org> 
     
    2425 
    2526#include <mach/regs-sdi.h> 
    2627#include <mach/regs-gpio.h> 
     28#include <mach/hardware.h> 
    2729 
    2830#include <plat/mci.h> 
    2931 
     32#include <asm/dma.h> 
     33#include <asm/dma-mapping.h> 
     34 
     35#include <asm/io.h> 
     36#include <mach/regs-gpio.h> 
     37#include <mach/mci.h> 
     38#include <mach/dma.h> 
     39 
    3040#include "s3cmci.h" 
    3141 
    3242#define DRIVER_NAME "s3c-mci" 
    static const int dbgmap_err = dbg_fail 
    4757static const int dbgmap_info  = dbg_info | dbg_conf; 
    4858static const int dbgmap_debug = dbg_err | dbg_debug; 
    4959 
     60static int f_max = -1; /* override maximum frequency limit */ 
     61static int persist; /* keep interface alive across suspend/resume */ 
     62 
    5063#define dbg(host, channels, args...)              \ 
    5164        do {                                      \ 
    5265        if (dbgmap_err & channels)                \ 
    static void do_pio_read(struct s3cmci_ho 
    280293                 * an even multiple of 4. */ 
    281294                if (fifo >= host->pio_bytes) 
    282295                        fifo = host->pio_bytes; 
    283                 else 
     296                else { 
    284297                        fifo -= fifo & 3; 
     298                        if (!fifo) 
     299                                break; 
     300                } 
    285301 
    286302                host->pio_bytes -= fifo; 
    287303                host->pio_count += fifo; 
    static void do_pio_write(struct s3cmci_h 
    329345 
    330346        to_ptr = host->base + host->sdidata; 
    331347 
    332         while ((fifo = fifo_free(host)) > 3) { 
     348        while ((fifo = fifo_free(host))) { 
    333349                if (!host->pio_bytes) { 
    334350                        res = get_data_buffer(host, &host->pio_bytes, 
    335351                                                        &host->pio_ptr); 
    static void do_pio_write(struct s3cmci_h 
    353369                 * words, so round down to an even multiple of 4. */ 
    354370                if (fifo >= host->pio_bytes) 
    355371                        fifo = host->pio_bytes; 
    356                 else 
     372                else { 
    357373                        fifo -= fifo & 3; 
     374                        if (!fifo) 
     375                                break; 
     376                } 
    358377 
    359378                host->pio_bytes -= fifo; 
    360379                host->pio_count += fifo; 
    static void pio_tasklet(unsigned long da 
    373392{ 
    374393        struct s3cmci_host *host = (struct s3cmci_host *) data; 
    375394 
    376  
    377395        disable_irq(host->irq); 
    378396 
    379397        if (host->pio_active == XFER_WRITE) 
    irq_out: 
    614632 
    615633        spin_unlock_irqrestore(&host->complete_lock, iflags); 
    616634        return IRQ_HANDLED; 
    617  
    618635} 
    619636 
    620637/* 
    static void s3cmci_dma_setup(struct s3cm 
    789806 
    790807        last_source = source; 
    791808 
    792         s3c2410_dma_devconfig(host->dma, source, 3, 
     809        s3c2410_dma_devconfig(host->dma, source, 
    793810                              host->mem->start + host->sdidata); 
    794811 
    795812        if (!setup_ok) { 
    796                 s3c2410_dma_config(host->dma, 4, 0); 
     813                s3c2410_dma_config(host->dma, 4); 
    797814                s3c2410_dma_set_buffdone_fn(host->dma, 
    798815                                            s3cmci_dma_done_callback); 
    799816                s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); 
    static void s3cmci_send_request(struct m 
    10261043                        dbg(host, dbg_err, "data prepare error %d\n", res); 
    10271044                        cmd->error = res; 
    10281045                        cmd->data->error = res; 
     1046                        cmd->data->error = -EIO; 
    10291047 
    10301048                        mmc_request_done(mmc, mrq); 
    10311049                        return; 
    static int __devinit s3cmci_probe(struct 
    12631281        host->is2440    = is2440; 
    12641282 
    12651283        host->pdata = pdev->dev.platform_data; 
    1266         if (!host->pdata) { 
    1267                 pdev->dev.platform_data = &s3cmci_def_pdata; 
     1284        if (!host->pdata) 
    12681285                host->pdata = &s3cmci_def_pdata; 
    1269         } 
    12701286 
    12711287        spin_lock_init(&host->complete_lock); 
    12721288        tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host); 
    static int __devinit s3cmci_probe(struct 
    13791395        mmc->f_min      = host->clk_rate / (host->clk_div * 256); 
    13801396        mmc->f_max      = host->clk_rate / host->clk_div; 
    13811397 
     1398        if (f_max >= 0) { 
     1399                unsigned f = f_max; 
     1400 
     1401                if (f < mmc->f_min) 
     1402                        f = mmc->f_min; 
     1403                if (mmc->f_max > f) { 
     1404                        dev_info(&pdev->dev, "f_max lowered from %u to %u Hz\n", 
     1405                            mmc->f_max, f); 
     1406                        mmc->f_max = f; 
     1407                } 
     1408        } 
     1409 
    13821410        if (host->pdata->ocr_avail) 
    13831411                mmc->ocr_avail = host->pdata->ocr_avail; 
    13841412 
    static int __devinit s3cmci_2440_probe(s 
    14911519 
    14921520#ifdef CONFIG_PM 
    14931521 
     1522static int save_regs(struct mmc_host *mmc) 
     1523{ 
     1524        struct s3cmci_host *host = mmc_priv(mmc); 
     1525        unsigned long flags; 
     1526        unsigned from; 
     1527        u32 *to = host->saved; 
     1528 
     1529        mmc_flush_scheduled_work(); 
     1530 
     1531        local_irq_save(flags); 
     1532        for (from = S3C2410_SDICON; from != S3C2410_SDIIMSK+4; from += 4) 
     1533                if (from != host->sdidata) 
     1534                        *to++ = readl(host->base + from); 
     1535        BUG_ON(to-host->saved != ARRAY_SIZE(host->saved)); 
     1536        local_irq_restore(flags); 
     1537 
     1538        return 0; 
     1539} 
     1540 
     1541static int restore_regs(struct mmc_host *mmc) 
     1542{ 
     1543        struct s3cmci_host *host = mmc_priv(mmc); 
     1544        unsigned long flags; 
     1545        unsigned to; 
     1546        u32 *from = host->saved; 
     1547 
     1548        /* 
     1549         * Before we begin with the necromancy, make sure we don't 
     1550         * inadvertently start something we'll regret microseconds later. 
     1551         */ 
     1552        from[S3C2410_SDICMDCON - S3C2410_SDICON] = 0; 
     1553 
     1554        local_irq_save(flags); 
     1555        for (to = S3C2410_SDICON; to != S3C2410_SDIIMSK+4; to += 4) 
     1556                if (to != host->sdidata) 
     1557                        writel(*from++, host->base + to); 
     1558        BUG_ON(from-host->saved != ARRAY_SIZE(host->saved)); 
     1559        local_irq_restore(flags); 
     1560 
     1561        return 0; 
     1562} 
     1563 
    14941564static int s3cmci_suspend(struct platform_device *dev, pm_message_t state) 
    14951565{ 
    14961566        struct mmc_host *mmc = platform_get_drvdata(dev); 
    14971567 
    1498         return mmc_suspend_host(mmc, state); 
     1568        return persist ? save_regs(mmc) : mmc_suspend_host(mmc, state); 
    14991569} 
    15001570 
    15011571static int s3cmci_resume(struct platform_device *dev) 
    15021572{ 
    15031573        struct mmc_host *mmc = platform_get_drvdata(dev); 
    15041574 
    1505         return mmc_resume_host(mmc); 
     1575        return persist ? restore_regs(mmc) : mmc_resume_host(mmc); 
    15061576} 
    15071577 
    15081578#else /* CONFIG_PM */ 
    static void __exit s3cmci_exit(void) 
    15601630module_init(s3cmci_init); 
    15611631module_exit(s3cmci_exit); 
    15621632 
     1633module_param(f_max, int, 0644); 
     1634module_param(persist, int, 0644); 
     1635 
    15631636MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver"); 
    15641637MODULE_LICENSE("GPL v2"); 
    15651638MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>"); 
    15661639MODULE_ALIAS("platform:s3c2410-sdi"); 
    15671640MODULE_ALIAS("platform:s3c2412-sdi"); 
    15681641MODULE_ALIAS("platform:s3c2440-sdi"); 
     1642 
  • drivers/mmc/host/s3cmci.h

    a b  
    88 * published by the Free Software Foundation. 
    99 */ 
    1010 
     11 
     12#include <mach/regs-sdi.h> 
     13#include <linux/regulator/consumer.h> 
     14 
    1115/* FIXME: DMA Resource management ?! */ 
    1216#define S3CMCI_DMA 0 
    1317 
    struct s3cmci_host { 
    6872        unsigned int            ccnt, dcnt; 
    6973        struct tasklet_struct   pio_tasklet; 
    7074 
     75        /* 
     76         * Here's where we save the registers during suspend. Note that we skip 
     77         * SDIDATA, which is at different positions on 2410 and 2440, so 
     78         * there's no "+1" in the array size. 
     79         */ 
     80        u32                     saved[(S3C2410_SDIIMSK-S3C2410_SDICON)/4]; 
     81 
    7182#ifdef CONFIG_CPU_FREQ 
    7283        struct notifier_block   freq_transition; 
    7384#endif 
     85 
     86        struct regulator *regulator; 
    7487}; 
  • new file drivers/mmc/host/sdhci-s3c.c

    - +  
     1/* linux/drivers/mmc/host/sdhci-s3c.c 
     2 * 
     3 * Copyright 2008 Openmoko Inc. 
     4 * Copyright 2008 Simtec Electronics 
     5 *      Ben Dooks <ben@simtec.co.uk> 
     6 *      http://armlinux.simtec.co.uk/ 
     7 * 
     8 * SDHCI (HSMMC) support for Samsung SoC 
     9 * 
     10 * This program is free software; you can redistribute it and/or modify 
     11 * it under the terms of the GNU General Public License version 2 as 
     12 * published by the Free Software Foundation. 
     13 */ 
     14 
     15#include <linux/delay.h> 
     16#include <linux/dma-mapping.h> 
     17#include <linux/platform_device.h> 
     18#include <linux/clk.h> 
     19#include <linux/io.h> 
     20 
     21#include <linux/mmc/host.h> 
     22 
     23#include <plat/regs-sdhci.h> 
     24#include <plat/sdhci.h> 
     25 
     26#include "sdhci.h" 
     27 
     28#define MAX_BUS_CLK     (4) 
     29 
     30struct sdhci_s3c { 
     31        struct sdhci_host       *host; 
     32        struct platform_device  *pdev; 
     33        struct resource         *ioarea; 
     34        struct s3c_sdhci_platdata *pdata; 
     35        unsigned int            cur_clk; 
     36 
     37        struct clk              *clk_io;        /* clock for io bus */ 
     38        struct clk              *clk_bus[MAX_BUS_CLK]; 
     39}; 
     40 
     41static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) 
     42{ 
     43        return sdhci_priv(host); 
     44} 
     45 
     46static u32 get_curclk(u32 ctrl2) 
     47{ 
     48        ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK; 
     49        ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; 
     50 
     51        return ctrl2; 
     52} 
     53 
     54static void sdhci_s3c_check_sclk(struct sdhci_host *host) 
     55{ 
     56        struct sdhci_s3c *ourhost = to_s3c(host); 
     57        u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2); 
     58 
     59        if (get_curclk(tmp) != ourhost->cur_clk) { 
     60                dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n"); 
     61 
     62                tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; 
     63                tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; 
     64                writel(tmp, host->ioaddr + 0x80); 
     65        } 
     66} 
     67 
     68static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) 
     69{ 
     70        struct sdhci_s3c *ourhost = to_s3c(host); 
     71        struct clk *busclk; 
     72        unsigned int rate, max; 
     73        int clk; 
     74 
     75        /* note, a reset will reset the clock source */ 
     76 
     77        sdhci_s3c_check_sclk(host); 
     78 
     79        for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) { 
     80                busclk = ourhost->clk_bus[clk]; 
     81                if (!busclk) 
     82                        continue; 
     83 
     84                rate = clk_get_rate(busclk); 
     85                if (rate > max) 
     86                        max = rate; 
     87        } 
     88 
     89        return max; 
     90} 
     91 
     92static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host) 
     93{ 
     94        return sdhci_s3c_get_max_clk(host) / 1000000; 
     95} 
     96 
     97static void sdhci_s3c_set_ios(struct sdhci_host *host, 
     98                              struct mmc_ios *ios) 
     99{ 
     100        struct sdhci_s3c *ourhost = to_s3c(host); 
     101        struct s3c_sdhci_platdata *pdata = ourhost->pdata; 
     102        int width; 
     103 
     104        sdhci_s3c_check_sclk(host); 
     105 
     106        if (ios->power_mode != MMC_POWER_OFF) { 
     107                switch (ios->bus_width) { 
     108                case MMC_BUS_WIDTH_4: 
     109                        width = 4; 
     110                        break; 
     111                case MMC_BUS_WIDTH_1: 
     112                        width = 1; 
     113                        break; 
     114                default: 
     115                        BUG(); 
     116                } 
     117 
     118                if (pdata->cfg_gpio) 
     119                        pdata->cfg_gpio(ourhost->pdev, width); 
     120        } 
     121 
     122        if (pdata->cfg_card) 
     123                pdata->cfg_card(ourhost->pdev, host->ioaddr, 
     124                                ios, host->mmc->card); 
     125} 
     126 
     127static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, 
     128                                             unsigned int src, 
     129                                             unsigned int wanted) 
     130{ 
     131        unsigned long rate; 
     132        struct clk *clksrc = ourhost->clk_bus[src]; 
     133        int div; 
     134 
     135        if (!clksrc) 
     136                return UINT_MAX; 
     137 
     138        rate = clk_get_rate(clksrc); 
     139 
     140        for (div = 1; div < 256; div *= 2) { 
     141                if ((rate / div) <= wanted) 
     142                        break; 
     143        } 
     144 
     145        dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", 
     146                src, rate, wanted, rate / div); 
     147 
     148        return (wanted - (rate / div)); 
     149} 
     150 
     151static void sdhci_s3c_change_clock(struct sdhci_host *host, unsigned int clock) 
     152{ 
     153        struct sdhci_s3c *ourhost = to_s3c(host); 
     154        unsigned int best = UINT_MAX; 
     155        unsigned int delta; 
     156        int best_src = 0; 
     157        int src; 
     158        u32 ctrl; 
     159 
     160        for (src = 0; src < MAX_BUS_CLK; src++) { 
     161                delta = sdhci_s3c_consider_clock(ourhost, src, clock); 
     162                if (delta < best) { 
     163                        best = delta; 
     164                        best_src = src; 
     165                } 
     166        } 
     167 
     168        dev_dbg(&ourhost->pdev->dev, 
     169                "selected source %d, clock %d, delta %d\n", 
     170                 best_src, clock, best); 
     171 
     172        /* turn clock off to card before changing clock source */ 
     173        writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); 
     174 
     175        /* select the new clock source */ 
     176 
     177        if (ourhost->cur_clk != best_src) { 
     178                struct clk *clk = ourhost->clk_bus[best_src]; 
     179 
     180                ourhost->cur_clk = best_src; 
     181                host->max_clk = clk_get_rate(clk); 
     182                host->timeout_clk = host->max_clk / 1000000; 
     183 
     184                ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); 
     185                ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; 
     186                ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; 
     187                writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2); 
     188        } 
     189 
     190        sdhci_change_clock(host, clock); 
     191} 
     192 
     193static struct sdhci_ops sdhci_s3c_ops = { 
     194        .get_max_clock          = sdhci_s3c_get_max_clk, 
     195        .get_timeout_clock      = sdhci_s3c_get_timeout_clk, 
     196        .change_clock           = sdhci_s3c_change_clock, 
     197        .set_ios                = sdhci_s3c_set_ios, 
     198}; 
     199 
     200/* 
     201 * call this when you need sd stack to recognize insertion or removal of card 
     202 * that can't be told by SDHCI regs 
     203 */ 
     204 
     205void sdhci_s3c_force_presence_change(struct platform_device *pdev) 
     206{ 
     207        struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; 
     208 
     209        dev_info(&pdev->dev, "sdhci_s3c_force_presence_change called\n"); 
     210        mmc_detect_change(pdata->sdhci_host->mmc, msecs_to_jiffies(200)); 
     211} 
     212EXPORT_SYMBOL_GPL(sdhci_s3c_force_presence_change); 
     213 
     214 
     215static int __devinit sdhci_s3c_probe(struct platform_device *pdev) 
     216{ 
     217        struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; 
     218        struct device *dev = &pdev->dev; 
     219        struct sdhci_host *host; 
     220        struct sdhci_s3c *sc; 
     221        struct resource *res; 
     222        int ret, irq, ptr, clks; 
     223 
     224        if (!pdata) { 
     225                dev_err(dev, "no device data specified\n"); 
     226                return -ENOENT; 
     227        } 
     228 
     229        irq = platform_get_irq(pdev, 0); 
     230        if (irq < 0) { 
     231                dev_err(dev, "no irq specified\n"); 
     232                return irq; 
     233        } 
     234 
     235        res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     236        if (!res) { 
     237                dev_err(dev, "no memory specified\n"); 
     238                return -ENOENT; 
     239        } 
     240 
     241        host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); 
     242        if (IS_ERR(host)) { 
     243                dev_err(dev, "sdhci_alloc_host() failed\n"); 
     244                return PTR_ERR(host); 
     245        } 
     246 
     247        pdata->sdhci_host = host; 
     248 
     249        sc = sdhci_priv(host); 
     250 
     251        sc->host = host; 
     252        sc->pdev = pdev; 
     253        sc->pdata = pdata; 
     254 
     255        platform_set_drvdata(pdev, host); 
     256 
     257        sc->clk_io = clk_get(dev, "hsmmc"); 
     258        if (IS_ERR(sc->clk_io)) { 
     259                dev_err(dev, "failed to get io clock\n"); 
     260                ret = PTR_ERR(sc->clk_io); 
     261                goto err_io_clk; 
     262        } 
     263 
     264        /* enable the local io clock and keep it running for the moment. */ 
     265        clk_enable(sc->clk_io); 
     266 
     267        for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { 
     268                struct clk *clk; 
     269                char *name = pdata->clocks[ptr]; 
     270 
     271                if (name == NULL) 
     272                        continue; 
     273 
     274                clk = clk_get(dev, name); 
     275                if (IS_ERR(clk)) { 
     276                        dev_err(dev, "failed to get clock %s\n", name); 
     277                        continue; 
     278                } 
     279 
     280                clks++; 
     281                sc->clk_bus[ptr] = clk; 
     282                clk_enable(clk); 
     283 
     284                dev_info(dev, "clock source %d: %s (%ld Hz)\n", 
     285                         ptr, name, clk_get_rate(clk)); 
     286        } 
     287 
     288        if (clks == 0) { 
     289                dev_err(dev, "failed to find any bus clocks\n"); 
     290                ret = -ENOENT; 
     291                goto err_no_busclks; 
     292        } 
     293 
     294        sc->ioarea = request_mem_region(res->start, resource_size(res), 
     295                                        mmc_hostname(host->mmc)); 
     296        if (!sc->ioarea) { 
     297                dev_err(dev, "failed to reserve register area\n"); 
     298                ret = -ENXIO; 
     299                goto err_req_regs; 
     300        } 
     301 
     302        host->ioaddr = ioremap_nocache(res->start, resource_size(res)); 
     303        if (!host->ioaddr) { 
     304                dev_err(dev, "failed to map registers\n"); 
     305                ret = -ENXIO; 
     306                goto err_req_regs; 
     307        } 
     308 
     309        /* Ensure we have minimal gpio selected CMD/CLK/Detect */ 
     310        if (pdata->cfg_gpio) 
     311                pdata->cfg_gpio(pdev, 0); 
     312 
     313        sdhci_s3c_check_sclk(host); 
     314 
     315        host->hw_name = "samsung-hsmmc"; 
     316        host->ops = &sdhci_s3c_ops; 
     317        host->quirks = 0; 
     318        host->irq = irq; 
     319 
     320        /* Setup quirks for the controller */ 
     321 
     322        /* Currently with ADMA enabled we are getting some length 
     323         * interrupts that are not being dealt with, do disable 
     324         * ADMA until this is sorted out. */ 
     325        host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; 
     326        host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE; 
     327 
     328        /* It seems we do not get an DATA transfer complete on non-busy 
     329         * transfers, not sure if this is a problem with this specific 
     330         * SDHCI block, or a missing configuration that needs to be set. */ 
     331        host->quirks |= SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY; 
     332 
     333        host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | 
     334                         SDHCI_QUIRK_32BIT_DMA_SIZE); 
     335 
     336        ret = sdhci_add_host(host); 
     337        if (ret) { 
     338                dev_err(dev, "sdhci_add_host() failed\n"); 
     339                goto err_add_host; 
     340        } 
     341 
     342        return 0; 
     343 
     344 err_add_host: 
     345        release_resource(sc->ioarea); 
     346        kfree(sc->ioarea); 
     347 
     348 err_req_regs: 
     349        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { 
     350                clk_disable(sc->clk_bus[ptr]); 
     351                clk_put(sc->clk_bus[ptr]); 
     352        } 
     353 
     354 err_no_busclks: 
     355        clk_disable(sc->clk_io); 
     356        clk_put(sc->clk_io); 
     357 
     358 err_io_clk: 
     359        sdhci_free_host(host); 
     360 
     361        return ret; 
     362} 
     363 
     364static int __devexit sdhci_s3c_remove(struct platform_device *pdev) 
     365{ 
     366        return 0; 
     367} 
     368 
     369#ifdef CONFIG_PM 
     370 
     371static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm) 
     372{ 
     373        struct sdhci_host *host = platform_get_drvdata(dev); 
     374 
     375        sdhci_suspend_host(host, pm); 
     376        return 0; 
     377} 
     378 
     379static int sdhci_s3c_resume(struct platform_device *dev) 
     380{ 
     381        struct sdhci_host *host = platform_get_drvdata(dev); 
     382 
     383        sdhci_resume_host(host); 
     384        return 0; 
     385} 
     386 
     387#else 
     388#define sdhci_s3c_suspend NULL 
     389#define sdhci_s3c_resume NULL 
     390#endif 
     391 
     392static struct platform_driver sdhci_s3c_driver = { 
     393        .probe          = sdhci_s3c_probe, 
     394        .remove         = __devexit_p(sdhci_s3c_remove), 
     395        .suspend        = sdhci_s3c_suspend, 
     396        .resume         = sdhci_s3c_resume, 
     397        .driver         = { 
     398                .owner  = THIS_MODULE, 
     399                .name   = "s3c-sdhci", 
     400        }, 
     401}; 
     402 
     403static int __init sdhci_s3c_init(void) 
     404{ 
     405        return platform_driver_register(&sdhci_s3c_driver); 
     406} 
     407 
     408static void __exit sdhci_s3c_exit(void) 
     409{ 
     410        platform_driver_unregister(&sdhci_s3c_driver); 
     411} 
     412 
     413module_init(sdhci_s3c_init); 
     414module_exit(sdhci_s3c_exit); 
     415 
     416MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue"); 
     417MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 
     418MODULE_LICENSE("GPL v2"); 
     419MODULE_ALIAS("platform:s3c-sdhci"); 
  • drivers/mtd/nand/s3c2410.c

    a b static int s3c2410_nand_correct_data(str 
    438438        if ((diff0 & ~(1<<fls(diff0))) == 0) 
    439439                return 1; 
    440440 
    441         return -1; 
     441        return -EBADMSG; 
    442442} 
    443443 
    444444/* ECC functions 
    static void s3c2410_nand_read_buf(struct 
    530530static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) 
    531531{ 
    532532        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 
     533        u8 *ptr = buf + (len & ~3); 
     534        int i; 
     535 
    533536        readsl(info->regs + S3C2440_NFDATA, buf, len / 4); 
     537        for (i = 0; i != (len & 3); i++) 
     538                ptr[i] = readb(info->regs + S3C2440_NFDATA); 
    534539} 
    535540 
    536541static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) 
    static int s3c2410_nand_remove(struct pl 
    645650} 
    646651 
    647652#ifdef CONFIG_MTD_PARTITIONS 
     653const char *part_probes[] = { "cmdlinepart", NULL }; 
    648654static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, 
    649655                                      struct s3c2410_nand_mtd *mtd, 
    650656                                      struct s3c2410_nand_set *set) 
    651657{ 
     658        struct mtd_partition *part_info; 
     659        int nr_part = 0; 
     660 
    652661        if (set == NULL) 
    653662                return add_mtd_device(&mtd->mtd); 
    654663 
    655         if (set->nr_partitions > 0 && set->partitions != NULL) { 
    656                 return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions); 
     664        if (set->nr_partitions == 0) { 
     665                mtd->mtd.name = set->name; 
     666                nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, 
     667                                                &part_info, 0); 
     668        } else { 
     669                if (set->nr_partitions > 0 && set->partitions != NULL) { 
     670                        nr_part = set->nr_partitions; 
     671                        part_info = set->partitions; 
     672                } 
    657673        } 
    658674 
     675        if (nr_part > 0 && part_info) 
     676                return add_mtd_partitions(&mtd->mtd, part_info, nr_part); 
     677 
    659678        return add_mtd_device(&mtd->mtd); 
    660679} 
    661680#else 
    static void s3c2410_nand_init_chip(struc 
    684703        chip->select_chip  = s3c2410_nand_select_chip; 
    685704        chip->chip_delay   = 50; 
    686705        chip->priv         = nmtd; 
    687         chip->options      = 0; 
    688706        chip->controller   = &info->controller; 
    689707 
     708        if (set->flags & S3C2410_NAND_BBT) 
     709                chip->options      = NAND_USE_FLASH_BBT; 
     710        else 
     711                chip->options      = 0; 
     712 
    690713        switch (info->cpu_type) { 
    691714        case TYPE_S3C2410: 
    692715                chip->IO_ADDR_W = regs + S3C2410_NFDATA; 
    static void s3c2410_nand_init_chip(struc 
    726749        nmtd->mtd.owner    = THIS_MODULE; 
    727750        nmtd->set          = set; 
    728751 
    729         if (hardware_ecc) { 
     752        if (!info->platform->software_ecc && hardware_ecc) { 
    730753                chip->ecc.calculate = s3c2410_nand_calculate_ecc; 
    731754                chip->ecc.correct   = s3c2410_nand_correct_data; 
    732755                chip->ecc.mode      = NAND_ECC_HW; 
  • drivers/mmc/core/core.c

    a b static int mmc_schedule_delayed_work(str 
    5959/* 
    6060 * Internal function. Flush all scheduled work from the MMC work queue. 
    6161 */ 
    62 static void mmc_flush_scheduled_work(void) 
     62void mmc_flush_scheduled_work(void) 
    6363{ 
    6464        flush_workqueue(workqueue); 
    6565} 
     66EXPORT_SYMBOL_GPL(mmc_flush_scheduled_work); 
    6667 
    6768/** 
    6869 *      mmc_request_done - finish processing an MMC request 
Note: See TracBrowser for help on using the repository browser.