diff options
Diffstat (limited to 'arch/arm/plat-nomadik')
-rw-r--r-- | arch/arm/plat-nomadik/gpio.c | 74 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/gpio.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/pincfg.h | 36 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/ske.h | 50 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/ste_dma40.h | 135 |
5 files changed, 205 insertions, 92 deletions
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 977c8f9..85e6fd21 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -102,6 +102,22 @@ static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); } +static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int val) +{ + if (val) + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS); + else + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC); +} + +static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int val) +{ + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); + __nmk_gpio_set_output(nmk_chip, offset, val); +} + static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, pin_cfg_t cfg) { @@ -118,20 +134,29 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, [3] /* illegal */ = "??" }; static const char *slpmnames[] = { - [NMK_GPIO_SLPM_INPUT] = "input", - [NMK_GPIO_SLPM_NOCHANGE] = "no-change", + [NMK_GPIO_SLPM_INPUT] = "input/wakeup", + [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", }; int pin = PIN_NUM(cfg); int pull = PIN_PULL(cfg); int af = PIN_ALT(cfg); int slpm = PIN_SLPM(cfg); + int output = PIN_DIR(cfg); + int val = PIN_VAL(cfg); - dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n", - pin, afnames[af], pullnames[pull], slpmnames[slpm]); + dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n", + pin, afnames[af], pullnames[pull], slpmnames[slpm], + output ? "output " : "input", + output ? (val ? "high" : "low") : ""); + + if (output) + __nmk_gpio_make_output(nmk_chip, offset, val); + else { + __nmk_gpio_make_input(nmk_chip, offset); + __nmk_gpio_set_pull(nmk_chip, offset, pull); + } - __nmk_gpio_make_input(nmk_chip, offset); - __nmk_gpio_set_pull(nmk_chip, offset, pull); __nmk_gpio_set_slpm(nmk_chip, offset, slpm); __nmk_gpio_set_mode(nmk_chip, offset, af); } @@ -200,6 +225,10 @@ EXPORT_SYMBOL(nmk_config_pins); * changed to an input (with pullup/down enabled) in sleep and deep sleep. If * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was * configured even when in sleep and deep sleep. + * + * On DB8500v2 onwards, this setting loses the previous meaning and instead + * indicates if wakeup detection is enabled on the pin. Note that + * enable_irq_wake() will automatically enable wakeup detection. */ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) { @@ -367,7 +396,27 @@ static void nmk_gpio_irq_unmask(unsigned int irq) static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on) { - return nmk_gpio_irq_modify(irq, WAKE, on); + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + int gpio; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + if (!nmk_chip) + return -EINVAL; + + spin_lock_irqsave(&nmk_chip->lock, flags); +#ifdef CONFIG_ARCH_U8500 + if (cpu_is_u8500v2()) { + __nmk_gpio_set_slpm(nmk_chip, gpio, + on ? NMK_GPIO_SLPM_WAKEUP_ENABLE + : NMK_GPIO_SLPM_WAKEUP_DISABLE); + } +#endif + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; } static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) @@ -495,12 +544,8 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, { struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); - u32 bit = 1 << offset; - if (val) - writel(bit, nmk_chip->addr + NMK_GPIO_DATS); - else - writel(bit, nmk_chip->addr + NMK_GPIO_DATC); + __nmk_gpio_set_output(nmk_chip, offset, val); } static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, @@ -509,8 +554,7 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); - writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); - nmk_gpio_set_output(chip, offset, val); + __nmk_gpio_make_output(nmk_chip, offset, val); return 0; } @@ -534,7 +578,7 @@ static struct gpio_chip nmk_gpio_template = { .can_sleep = 0, }; -static int __init nmk_gpio_probe(struct platform_device *dev) +static int __devinit nmk_gpio_probe(struct platform_device *dev) { struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; struct nmk_gpio_chip *nmk_chip; diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index aba3551..67b113d 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -65,7 +65,9 @@ enum nmk_gpio_pull { /* Sleep mode */ enum nmk_gpio_slpm { NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, NMK_GPIO_SLPM_NOCHANGE, + NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, }; extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode); diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 7eed11c..8c5ae3f 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -19,12 +19,16 @@ * bit 9..10 - Alternate Function Selection * bit 11..12 - Pull up/down state * bit 13 - Sleep mode behaviour + * bit 14 - (sleep mode) Direction + * bit 15 - (sleep mode) Value (if output) * * to facilitate the definition, the following macros are provided * * PIN_CFG_DEFAULT - default config (0): * pull up/down = disabled - * sleep mode = input + * sleep mode = input/wakeup + * (sleep mode) direction = input + * (sleep mode) value = low * * PIN_CFG - default config with alternate function * PIN_CFG_PULL - default config with alternate function and pull up/down @@ -53,8 +57,36 @@ typedef unsigned long pin_cfg_t; #define PIN_SLPM_SHIFT 13 #define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) #define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) -#define PIN_SLPM_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) +#define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) #define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) +/* These two replace the above in DB8500v2+ */ +#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) + +#define PIN_DIR_SHIFT 14 +#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) +#define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT) +#define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT) +#define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT) + +#define PIN_VAL_SHIFT 15 +#define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT) +#define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT) +#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) +#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) + +/* Shortcuts. Use these instead of separate DIR and VAL. */ +#define PIN_INPUT PIN_DIR_INPUT +#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) +#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) + +/* + * These are the same as the ones above, but should make more sense to the + * reader when seen along with a setting a pin to AF mode. + */ +#define PIN_SLPM_INPUT PIN_INPUT +#define PIN_SLPM_OUTPUT_LOW PIN_OUTPUT_LOW +#define PIN_SLPM_OUTPUT_HIGH PIN_OUTPUT_HIGH #define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) diff --git a/arch/arm/plat-nomadik/include/plat/ske.h b/arch/arm/plat-nomadik/include/plat/ske.h new file mode 100644 index 0000000..31382fb --- /dev/null +++ b/arch/arm/plat-nomadik/include/plat/ske.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com> + * + * ux500 Scroll key and Keypad Encoder (SKE) header + */ + +#ifndef __SKE_H +#define __SKE_H + +#include <linux/input/matrix_keypad.h> + +/* register definitions for SKE peripheral */ +#define SKE_CR 0x00 +#define SKE_VAL0 0x04 +#define SKE_VAL1 0x08 +#define SKE_DBCR 0x0C +#define SKE_IMSC 0x10 +#define SKE_RIS 0x14 +#define SKE_MIS 0x18 +#define SKE_ICR 0x1C + +/* + * Keypad module + */ + +/** + * struct keypad_platform_data - structure for platform specific data + * @init: pointer to keypad init function + * @exit: pointer to keypad deinitialisation function + * @keymap_data: matrix scan code table for keycodes + * @krow: maximum number of rows + * @kcol: maximum number of columns + * @debounce_ms: platform specific debounce time + * @no_autorepeat: flag for auto repetition + * @wakeup_enable: allow waking up the system + */ +struct ske_keypad_platform_data { + int (*init)(void); + int (*exit)(void); + const struct matrix_keymap_data *keymap_data; + u8 krow; + u8 kcol; + u8 debounce_ms; + bool no_autorepeat; + bool wakeup_enable; +}; +#endif /*__SKE_KPD_H*/ diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 5fbde4b..74b62f1 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -1,10 +1,8 @@ /* - * arch/arm/plat-nomadik/include/plat/ste_dma40.h - * - * Copyright (C) ST-Ericsson 2007-2010 + * Copyright (C) ST-Ericsson SA 2007-2010 + * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson * License terms: GNU General Public License (GPL) version 2 - * Author: Per Friden <per.friden@stericsson.com> - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> */ @@ -14,43 +12,25 @@ #include <linux/dmaengine.h> #include <linux/workqueue.h> #include <linux/interrupt.h> -#include <linux/dmaengine.h> /* dev types for memcpy */ #define STEDMA40_DEV_DST_MEMORY (-1) #define STEDMA40_DEV_SRC_MEMORY (-1) -/* - * Description of bitfields of channel_type variable is available in - * the info structure. - */ +enum stedma40_mode { + STEDMA40_MODE_LOGICAL = 0, + STEDMA40_MODE_PHYSICAL, + STEDMA40_MODE_OPERATION, +}; -/* Priority */ -#define STEDMA40_INFO_PRIO_TYPE_POS 2 -#define STEDMA40_HIGH_PRIORITY_CHANNEL (0x1 << STEDMA40_INFO_PRIO_TYPE_POS) -#define STEDMA40_LOW_PRIORITY_CHANNEL (0x2 << STEDMA40_INFO_PRIO_TYPE_POS) - -/* Mode */ -#define STEDMA40_INFO_CH_MODE_TYPE_POS 6 -#define STEDMA40_CHANNEL_IN_PHY_MODE (0x1 << STEDMA40_INFO_CH_MODE_TYPE_POS) -#define STEDMA40_CHANNEL_IN_LOG_MODE (0x2 << STEDMA40_INFO_CH_MODE_TYPE_POS) -#define STEDMA40_CHANNEL_IN_OPER_MODE (0x3 << STEDMA40_INFO_CH_MODE_TYPE_POS) - -/* Mode options */ -#define STEDMA40_INFO_CH_MODE_OPT_POS 8 -#define STEDMA40_PCHAN_BASIC_MODE (0x1 << STEDMA40_INFO_CH_MODE_OPT_POS) -#define STEDMA40_PCHAN_MODULO_MODE (0x2 << STEDMA40_INFO_CH_MODE_OPT_POS) -#define STEDMA40_PCHAN_DOUBLE_DST_MODE (0x3 << STEDMA40_INFO_CH_MODE_OPT_POS) -#define STEDMA40_LCHAN_SRC_PHY_DST_LOG (0x1 << STEDMA40_INFO_CH_MODE_OPT_POS) -#define STEDMA40_LCHAN_SRC_LOG_DST_PHS (0x2 << STEDMA40_INFO_CH_MODE_OPT_POS) -#define STEDMA40_LCHAN_SRC_LOG_DST_LOG (0x3 << STEDMA40_INFO_CH_MODE_OPT_POS) - -/* Interrupt */ -#define STEDMA40_INFO_TIM_POS 10 -#define STEDMA40_NO_TIM_FOR_LINK (0x0 << STEDMA40_INFO_TIM_POS) -#define STEDMA40_TIM_FOR_LINK (0x1 << STEDMA40_INFO_TIM_POS) - -/* End of channel_type configuration */ +enum stedma40_mode_opt { + STEDMA40_PCHAN_BASIC_MODE = 0, + STEDMA40_LCHAN_SRC_LOG_DST_LOG = 0, + STEDMA40_PCHAN_MODULO_MODE, + STEDMA40_PCHAN_DOUBLE_DST_MODE, + STEDMA40_LCHAN_SRC_PHY_DST_LOG, + STEDMA40_LCHAN_SRC_LOG_DST_PHY, +}; #define STEDMA40_ESIZE_8_BIT 0x0 #define STEDMA40_ESIZE_16_BIT 0x1 @@ -73,16 +53,14 @@ #define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8 #define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16 +/* Maximum number of possible physical channels */ +#define STEDMA40_MAX_PHYS 32 + enum stedma40_flow_ctrl { STEDMA40_NO_FLOW_CTRL, STEDMA40_FLOW_CTRL, }; -enum stedma40_endianess { - STEDMA40_LITTLE_ENDIAN, - STEDMA40_BIG_ENDIAN -}; - enum stedma40_periph_data_width { STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT, STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT, @@ -90,15 +68,8 @@ enum stedma40_periph_data_width { STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT }; -struct stedma40_half_channel_info { - enum stedma40_endianess endianess; - enum stedma40_periph_data_width data_width; - int psize; - enum stedma40_flow_ctrl flow_ctrl; -}; - enum stedma40_xfer_dir { - STEDMA40_MEM_TO_MEM, + STEDMA40_MEM_TO_MEM = 1, STEDMA40_MEM_TO_PERIPH, STEDMA40_PERIPH_TO_MEM, STEDMA40_PERIPH_TO_PERIPH @@ -106,18 +77,31 @@ enum stedma40_xfer_dir { /** + * struct stedma40_chan_cfg - dst/src channel configuration + * + * @big_endian: true if the src/dst should be read as big endian + * @data_width: Data width of the src/dst hardware + * @p_size: Burst size + * @flow_ctrl: Flow control on/off. + */ +struct stedma40_half_channel_info { + bool big_endian; + enum stedma40_periph_data_width data_width; + int psize; + enum stedma40_flow_ctrl flow_ctrl; +}; + +/** * struct stedma40_chan_cfg - Structure to be filled by client drivers. * * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH - * @channel_type: priority, mode, mode options and interrupt configuration. + * @high_priority: true if high-priority + * @mode: channel mode: physical, logical, or operation + * @mode_opt: options for the chosen channel mode * @src_dev_type: Src device type * @dst_dev_type: Dst device type * @src_info: Parameters for dst half channel * @dst_info: Parameters for dst half channel - * @pre_transfer_data: Data to be passed on to the pre_transfer() function. - * @pre_transfer: Callback used if needed before preparation of transfer. - * Only called if device is set. size of bytes to transfer - * (in case of multiple element transfer size is size of the first element). * * * This structure has to be filled by the client drivers. @@ -126,15 +110,13 @@ enum stedma40_xfer_dir { */ struct stedma40_chan_cfg { enum stedma40_xfer_dir dir; - unsigned int channel_type; + bool high_priority; + enum stedma40_mode mode; + enum stedma40_mode_opt mode_opt; int src_dev_type; int dst_dev_type; struct stedma40_half_channel_info src_info; struct stedma40_half_channel_info dst_info; - void *pre_transfer_data; - int (*pre_transfer) (struct dma_chan *chan, - void *data, - int size); }; /** @@ -147,7 +129,6 @@ struct stedma40_chan_cfg { * @memcpy_len: length of memcpy * @memcpy_conf_phy: default configuration of physical channel memcpy * @memcpy_conf_log: default configuration of logical channel memcpy - * @llis_per_log: number of max linked list items per logical channel * @disabled_channels: A vector, ending with -1, that marks physical channels * that are for different reasons not available for the driver. */ @@ -159,23 +140,10 @@ struct stedma40_platform_data { u32 memcpy_len; struct stedma40_chan_cfg *memcpy_conf_phy; struct stedma40_chan_cfg *memcpy_conf_log; - unsigned int llis_per_log; - int disabled_channels[8]; + int disabled_channels[STEDMA40_MAX_PHYS]; }; -/** - * setdma40_set_psize() - Used for changing the package size of an - * already configured dma channel. - * - * @chan: dmaengine handle - * @src_psize: new package side for src. (STEDMA40_PSIZE*) - * @src_psize: new package side for dst. (STEDMA40_PSIZE*) - * - * returns 0 on ok, otherwise negative error number. - */ -int stedma40_set_psize(struct dma_chan *chan, - int src_psize, - int dst_psize); +#ifdef CONFIG_STE_DMA40 /** * stedma40_filter() - Provides stedma40_chan_cfg to the @@ -238,4 +206,21 @@ dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, direction, flags); } +#else +static inline bool stedma40_filter(struct dma_chan *chan, void *data) +{ + return false; +} + +static inline struct +dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, + dma_addr_t addr, + unsigned int size, + enum dma_data_direction direction, + unsigned long flags) +{ + return NULL; +} +#endif + #endif |