diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index d187e9f7cf1cf8b7fcd5bda6c6507558360a9237..1196290082d1ed176c03d3f985bf2539028b35c3 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -7,6 +7,12 @@ PIT Timer required properties: - interrupts: Should contain interrupt for the PIT which is the IRQ line shared across all System Controller members. +System Timer (ST) required properties: +- compatible: Should be "atmel,at91rm9200-st" +- reg: Should contain registers location and length +- interrupts: Should contain interrupt for the ST which is the IRQ line + shared across all System Controller members. + TC/TCLIB Timer required properties: - compatible: Should be "atmel,-tcb". can be "at91rm9200" or "at91sam9x5" diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index 4e16ba4feab0f309071ffb75e866e1a8980b7700..a33628759d36e10a0c4b2c181458311134561eaa 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes: gpio-controller; }; +2.1) gpio-controller and pinctrl subsystem +------------------------------------------ +gpio-controller on a SOC might be tightly coupled with the pinctrl +subsystem, in the sense that the pins can be used by other functions +together with optional gpio feature. + +While the pin allocation is totally managed by the pin ctrl subsystem, +gpio (under gpiolib) is still maintained by gpio drivers. It may happen +that different pin ranges in a SoC is managed by different gpio drivers. + +This makes it logical to let gpio drivers announce their pin ranges to +the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to +request the corresponding pin before any gpio usage. + +For this, the gpio controller can use a pinctrl phandle and pins to +announce the pinrange to the pin ctrl subsystem. For example, + + qe_pio_e: gpio-controller@1460 { + #gpio-cells = <2>; + compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank"; + reg = <0x1460 0x18>; + gpio-controller; + gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>; + + } + +where, + &pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node. + + Next values specify the base pin and number of pins for the range + handled by 'qe_pio_e' gpio. In the given example from base pin 20 to + pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled + by this gpio controller. + +The pinctrl node must have "#gpio-range-cells" property to show number of +arguments to pass with phandle from gpio controllers node. diff --git a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt index 66efc804806adf4124f36b359c09670dc006bd39..85f8c0d084fab7b0b4bf1ee862ef96eafbf046c2 100644 --- a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt +++ b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt @@ -9,6 +9,10 @@ Required properties: unused). - gpio-controller: Marks the device node as a GPIO controller. +optional properties: +- #gpio-lines: Number of gpio if absent 32. + + Example: pioA: gpio@fffff200 { compatible = "atmel,at91rm9200-gpio"; @@ -16,5 +20,6 @@ Example: interrupts = <2 4>; #gpio-cells = <2>; gpio-controller; + #gpio-lines = <19>; }; diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt new file mode 100644 index 0000000000000000000000000000000000000000..3a268127b0547e08f167635d2b14a4a04e9a3ac8 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt @@ -0,0 +1,141 @@ +* Atmel AT91 Pinmux Controller + +The AT91 Pinmux Controler, enables the IC +to share one PAD to several functional blocks. The sharing is done by +multiplexing the PAD input/output signals. For each PAD there are up to +8 muxing options (called periph modes). Since different modules require +different PAD settings (like pull up, keeper, etc) the contoller controls +also the PAD settings parameters. + +Please refer to pinctrl-bindings.txt in this directory for details of the +common pinctrl bindings used by client devices, including the meaning of the +phrase "pin configuration node". + +Atmel AT91 pin configuration node is a node of a group of pins which can be +used for a specific device or function. This node represents both mux and config +of the pins in that group. The 'pins' selects the function mode(also named pin +mode) this pin can work on and the 'config' configures various pad settings +such as pull-up, multi drive, etc. + +Required properties for iomux controller: +- compatible: "atmel,at91rm9200-pinctrl" +- atmel,mux-mask: array of mask (periph per bank) to describe if a pin can be + configured in this periph mode. All the periph and bank need to be describe. + +How to create such array: + +Each column will represent the possible peripheral of the pinctrl +Each line will represent a pio bank + +Take an example on the 9260 +Peripheral: 2 ( A and B) +Bank: 3 (A, B and C) +=> + + /* A B */ + 0xffffffff 0xffc00c3b /* pioA */ + 0xffffffff 0x7fff3ccf /* pioB */ + 0xffffffff 0x007fffff /* pioC */ + +For each peripheral/bank we will descibe in a u32 if a pin can can be +configured in it by putting 1 to the pin bit (1 << pin) + +Let's take the pioA on peripheral B +From the datasheet Table 10-2. +Peripheral B +PA0 MCDB0 +PA1 MCCDB +PA2 +PA3 MCDB3 +PA4 MCDB2 +PA5 MCDB1 +PA6 +PA7 +PA8 +PA9 +PA10 ETX2 +PA11 ETX3 +PA12 +PA13 +PA14 +PA15 +PA16 +PA17 +PA18 +PA19 +PA20 +PA21 +PA22 ETXER +PA23 ETX2 +PA24 ETX3 +PA25 ERX2 +PA26 ERX3 +PA27 ERXCK +PA28 ECRS +PA29 ECOL +PA30 RXD4 +PA31 TXD4 + +=> 0xffc00c3b + +Required properties for pin configuration node: +- atmel,pins: 4 integers array, represents a group of pins mux and config + setting. The format is atmel,pins = . + The PERIPH 0 means gpio. + +Bits used for CONFIG: +PULL_UP (1 << 0): indicate this pin need a pull up. +MULTIDRIVE (1 << 1): indicate this pin need to be configured as multidrive. +DEGLITCH (1 << 2): indicate this pin need deglitch. +PULL_DOWN (1 << 3): indicate this pin need a pull down. +DIS_SCHMIT (1 << 4): indicate this pin need to disable schmit trigger. +DEBOUNCE (1 << 16): indicate this pin need debounce. +DEBOUNCE_VAL (0x3fff << 17): debounce val. + +NOTE: +Some requirements for using atmel,at91rm9200-pinctrl binding: +1. We have pin function node defined under at91 controller node to represent + what pinmux functions this SoC supports. +2. The driver can use the function node's name and pin configuration node's + name describe the pin function and group hierarchy. + For example, Linux at91 pinctrl driver takes the function node's name + as the function name and pin configuration node's name as group name to + create the map table. +3. Each pin configuration node should have a phandle, devices can set pins + configurations by referring to the phandle of that pin configuration node. +4. The gpio controller must be describe in the pinctrl simple-bus. + +Examples: + +pinctrl@fffff400 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + reg = <0xfffff400 0x600>; + + atmel,mux-mask = < + /* A B */ + 0xffffffff 0xffc00c3b /* pioA */ + 0xffffffff 0x7fff3ccf /* pioB */ + 0xffffffff 0x007fffff /* pioC */ + >; + + /* shared pinctrl settings */ + dbgu { + pinctrl_dbgu: dbgu-0 { + atmel,pins = + <1 14 0x1 0x0 /* PB14 periph A */ + 1 15 0x1 0x1>; /* PB15 periph with pullup */ + }; + }; +}; + +dbgu: serial@fffff200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfffff200 0x200>; + interrupts = <1 4 7>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dbgu>; + status = "disabled"; +}; diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index e08a883de36e316715bcdacebf9670f952c0de02..77a1d11af723282625dd3c3f326a5b6576fb437c 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt @@ -439,6 +439,48 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its signaling rate accordingly. +GPIO controllers and the pinctrl subsystem +------------------------------------------ + +A GPIO controller on a SOC might be tightly coupled with the pinctrl +subsystem, in the sense that the pins can be used by other functions +together with an optional gpio feature. We have already covered the +case where e.g. a GPIO controller need to reserve a pin or set the +direction of a pin by calling any of: + +pinctrl_request_gpio() +pinctrl_free_gpio() +pinctrl_gpio_direction_input() +pinctrl_gpio_direction_output() + +But how does the pin control subsystem cross-correlate the GPIO +numbers (which are a global business) to a certain pin on a certain +pin controller? + +This is done by registering "ranges" of pins, which are essentially +cross-reference tables. These are described in +Documentation/pinctrl.txt + +While the pin allocation is totally managed by the pinctrl subsystem, +gpio (under gpiolib) is still maintained by gpio drivers. It may happen +that different pin ranges in a SoC is managed by different gpio drivers. + +This makes it logical to let gpio drivers announce their pin ranges to +the pin ctrl subsystem before it will call 'pinctrl_request_gpio' in order +to request the corresponding pin to be prepared by the pinctrl subsystem +before any gpio usage. + +For this, the gpio controller can register its pin range with pinctrl +subsystem. There are two ways of doing it currently: with or without DT. + +For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt. + +For non-DT support, user can call gpiochip_add_pin_range() with appropriate +parameters to register a range of gpio pins with a pinctrl driver. For this +exact name string of pinctrl device has to be passed as one of the +argument to this routine. + + What do these conventions omit? =============================== One of the biggest things these conventions omit is pin multiplexing, since diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 3b4ee5328868cea31b024ad9631a286886826c60..da40efbef6ec5599406a1e086f7b11aaaa06e018 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -364,6 +364,9 @@ will get an pin number into its handled number range. Further it is also passed the range ID value, so that the pin controller knows which range it should deal with. +Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see +section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind +pinctrl and gpio drivers. PINMUX interfaces ================= @@ -1193,4 +1196,6 @@ foo_switch() ... } -The above has to be done from process context. +The above has to be done from process context. The reservation of the pins +will be done when the state is activated, so in effect one specific pin +can be used by different functions at different times on a running system. diff --git a/MAINTAINERS b/MAINTAINERS index 3d3abbacc1a32823af34de166e8b5d867eb5dbfa..d02cdb596d3576079e28800a246ff38cadd7f5c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5689,6 +5689,12 @@ S: Maintained F: drivers/pinctrl/ F: include/linux/pinctrl/ +PIN CONTROLLER - ATMEL AT91 +M: Jean-Christophe Plagniol-Villard +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: drivers/pinctrl/pinctrl-at91.c + PIN CONTROLLER - ST SPEAR M: Viresh Kumar L: spear-devel@list.st.com diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9759fec0b704559454ce8e054eaaa5b6d7c25335..67f1fdbad7f9b0bd949d5c140db8b1d23cee5db9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -330,6 +330,8 @@ config ARCH_AT91 select IRQ_DOMAIN select NEED_MACH_GPIO_H select NEED_MACH_IO_H if PCCARD + select PINCTRL + select PINCTRL_AT91 if USE_OF help This enables support for systems based on Atmel AT91RM9200 and AT91SAM9* processors. @@ -587,6 +589,7 @@ config ARCH_MMP select GPIO_PXA select IRQ_DOMAIN select NEED_MACH_GPIO_H + select PINCTRL select PLAT_PXA select SPARSE_IRQ help diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f37cf9fa5fa073318b3c6faad5d0a1480bd99826..fb5b07737ca71492ca8e352ee562bb2d3c246e33 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1,21 +1,37 @@ ifeq ($(CONFIG_OF),y) -dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb \ - at91sam9263ek.dtb \ - at91sam9g20ek_2mmc.dtb \ - at91sam9g20ek.dtb \ - at91sam9g25ek.dtb \ - at91sam9m10g45ek.dtb \ - at91sam9n12ek.dtb \ - ethernut5.dtb \ - evk-pro3.dtb \ - kizbox.dtb \ - tny_a9260.dtb \ - tny_a9263.dtb \ - tny_a9g20.dtb \ - usb_a9260.dtb \ - usb_a9263.dtb \ - usb_a9g20.dtb +# Keep at91 dtb files sorted alphabetically for each SoC +# rm9200 +dtb-$(CONFIG_ARCH_AT91) += at91rm9200ek.dtb +# sam9260 +dtb-$(CONFIG_ARCH_AT91) += animeo_ip.dtb +dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb +dtb-$(CONFIG_ARCH_AT91) += ethernut5.dtb +dtb-$(CONFIG_ARCH_AT91) += evk-pro3.dtb +dtb-$(CONFIG_ARCH_AT91) += tny_a9260.dtb +dtb-$(CONFIG_ARCH_AT91) += usb_a9260.dtb +# sam9263 +dtb-$(CONFIG_ARCH_AT91) += at91sam9263ek.dtb +dtb-$(CONFIG_ARCH_AT91) += tny_a9263.dtb +dtb-$(CONFIG_ARCH_AT91) += usb_a9263.dtb +# sam9g20 +dtb-$(CONFIG_ARCH_AT91) += at91sam9g20ek.dtb +dtb-$(CONFIG_ARCH_AT91) += at91sam9g20ek_2mmc.dtb +dtb-$(CONFIG_ARCH_AT91) += kizbox.dtb +dtb-$(CONFIG_ARCH_AT91) += tny_a9g20.dtb +dtb-$(CONFIG_ARCH_AT91) += usb_a9g20.dtb +# sam9g45 +dtb-$(CONFIG_ARCH_AT91) += at91sam9m10g45ek.dtb +dtb-$(CONFIG_ARCH_AT91) += pm9g45.dtb +# sam9n12 +dtb-$(CONFIG_ARCH_AT91) += at91sam9n12ek.dtb +# sam9x5 +dtb-$(CONFIG_ARCH_AT91) += at91sam9g15ek.dtb +dtb-$(CONFIG_ARCH_AT91) += at91sam9g25ek.dtb +dtb-$(CONFIG_ARCH_AT91) += at91sam9g35ek.dtb +dtb-$(CONFIG_ARCH_AT91) += at91sam9x25ek.dtb +dtb-$(CONFIG_ARCH_AT91) += at91sam9x35ek.dtb + dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \ dove-cubox.dtb \ diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/animeo_ip.dts new file mode 100644 index 0000000000000000000000000000000000000000..74d92cd29d877454f5b4c1a660e2288519c65547 --- /dev/null +++ b/arch/arm/boot/dts/animeo_ip.dts @@ -0,0 +1,178 @@ +/* + * animeo_ip.dts - Device Tree file for Somfy Animeo IP Boards + * + * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2 only. + */ + +/dts-v1/; +/include/ "at91sam9260.dtsi" + +/ { + model = "Somfy Animeo IP"; + compatible = "somfy,animeo-ip", "atmel,at91sam9260", "atmel,at91sam9"; + + aliases { + serial0 = &usart1; + serial1 = &usart2; + serial2 = &usart0; + serial3 = &dbgu; + serial4 = &usart3; + serial5 = &uart0; + serial6 = &uart1; + }; + + chosen { + linux,stdout-path = &usart2; + }; + + memory { + reg = <0x20000000 0x4000000>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + main_clock: clock@0 { + compatible = "atmel,osc", "fixed-clock"; + clock-frequency = <18432000>; + }; + }; + + ahb { + apb { + usart0: serial@fffb0000 { + pinctrl-0 = <&pinctrl_usart0 &pinctrl_usart0_rts>; + linux,rs485-enabled-at-boot-time; + status = "okay"; + }; + + usart1: serial@fffb4000 { + pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts>; + linux,rs485-enabled-at-boot-time; + status = "okay"; + }; + + usart2: serial@fffb8000 { + pinctrl-0 = <&pinctrl_usart2>; + status = "okay"; + }; + + macb0: ethernet@fffc4000 { + pinctrl-0 = <&pinctrl_macb_rmii &pinctrl_macb_rmii_mii>; + phy-mode = "mii"; + status = "okay"; + }; + + mmc0: mmc@fffa8000 { + pinctrl-0 = <&pinctrl_mmc0_clk + &pinctrl_mmc0_slot1_cmd_dat0 + &pinctrl_mmc0_slot1_dat1_3>; + status = "okay"; + + slot@1 { + reg = <1>; + bus-width = <4>; + }; + }; + }; + + nand0: nand@40000000 { + nand-bus-width = <8>; + nand-ecc-mode = "soft"; + nand-on-flash-bbt; + status = "okay"; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x0 0x8000>; + }; + + barebox@8000 { + label = "barebox"; + reg = <0x8000 0x40000>; + }; + + bareboxenv@48000 { + label = "bareboxenv"; + reg = <0x48000 0x8000>; + }; + + user_block@0x50000 { + label = "user_block"; + reg = <0x50000 0xb0000>; + }; + + kernel@100000 { + label = "kernel"; + reg = <0x100000 0x1b0000>; + }; + + root@2b0000 { + label = "root"; + reg = <0x2b0000 0x1D50000>; + }; + }; + + usb0: ohci@00500000 { + num-ports = <2>; + atmel,vbus-gpio = <&pioB 15 1>; + status = "okay"; + }; + }; + + leds { + compatible = "gpio-leds"; + + power_green { + label = "power_green"; + gpios = <&pioC 17 0>; + linux,default-trigger = "heartbeat"; + }; + + power_red { + label = "power_red"; + gpios = <&pioA 2 0>; + }; + + tx_green { + label = "tx_green"; + gpios = <&pioC 19 0>; + }; + + tx_red { + label = "tx_red"; + gpios = <&pioC 18 0>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + + keyswitch_in { + label = "keyswitch_in"; + gpios = <&pioB 1 0>; + linux,code = <28>; + gpio-key,wakeup; + }; + + error_in { + label = "error_in"; + gpios = <&pioB 2 0>; + linux,code = <29>; + gpio-key,wakeup; + }; + + btn { + label = "btn"; + gpios = <&pioC 23 0>; + linux,code = <31>; + gpio-key,wakeup; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..e154f242c680e0ca3db90aabf823490dcb146607 --- /dev/null +++ b/arch/arm/boot/dts/at91rm9200.dtsi @@ -0,0 +1,349 @@ +/* + * at91rm9200.dtsi - Device Tree Include file for AT91RM9200 family SoC + * + * Copyright (C) 2011 Atmel, + * 2011 Nicolas Ferre , + * 2012 Joachim Eastwood + * + * Based on at91sam9260.dtsi + * + * Licensed under GPLv2 or later. + */ + +/include/ "skeleton.dtsi" + +/ { + model = "Atmel AT91RM9200 family SoC"; + compatible = "atmel,at91rm9200"; + interrupt-parent = <&aic>; + + aliases { + serial0 = &dbgu; + serial1 = &usart0; + serial2 = &usart1; + serial3 = &usart2; + serial4 = &usart3; + gpio0 = &pioA; + gpio1 = &pioB; + gpio2 = &pioC; + gpio3 = &pioD; + tcb0 = &tcb0; + tcb1 = &tcb1; + }; + cpus { + cpu@0 { + compatible = "arm,arm920t"; + }; + }; + + memory { + reg = <0x20000000 0x04000000>; + }; + + ahb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + apb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + aic: interrupt-controller@fffff000 { + #interrupt-cells = <3>; + compatible = "atmel,at91rm9200-aic"; + interrupt-controller; + reg = <0xfffff000 0x200>; + atmel,external-irqs = <25 26 27 28 29 30 31>; + }; + + ramc0: ramc@ffffff00 { + compatible = "atmel,at91rm9200-sdramc"; + reg = <0xffffff00 0x100>; + }; + + pmc: pmc@fffffc00 { + compatible = "atmel,at91rm9200-pmc"; + reg = <0xfffffc00 0x100>; + }; + + st: timer@fffffd00 { + compatible = "atmel,at91rm9200-st"; + reg = <0xfffffd00 0x100>; + interrupts = <1 4 7>; + }; + + tcb0: timer@fffa0000 { + compatible = "atmel,at91rm9200-tcb"; + reg = <0xfffa0000 0x100>; + interrupts = <17 4 0 18 4 0 19 4 0>; + }; + + tcb1: timer@fffa4000 { + compatible = "atmel,at91rm9200-tcb"; + reg = <0xfffa4000 0x100>; + interrupts = <20 4 0 21 4 0 22 4 0>; + }; + + pinctrl@fffff400 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + ranges = <0xfffff400 0xfffff400 0x800>; + + atmel,mux-mask = < + /* A B */ + 0xffffffff 0xffffffff /* pioA */ + 0xffffffff 0x083fffff /* pioB */ + 0xffff3fff 0x00000000 /* pioC */ + 0x03ff87ff 0x0fffff80 /* pioD */ + >; + + /* shared pinctrl settings */ + dbgu { + pinctrl_dbgu: dbgu-0 { + atmel,pins = + <0 30 0x1 0x0 /* PA30 periph A */ + 0 31 0x1 0x1>; /* PA31 periph with pullup */ + }; + }; + + uart0 { + pinctrl_uart0: uart0-0 { + atmel,pins = + <0 17 0x1 0x0 /* PA17 periph A */ + 0 18 0x1 0x0>; /* PA18 periph A */ + }; + + pinctrl_uart0_rts: uart0_rts-0 { + atmel,pins = + <0 20 0x1 0x0>; /* PA20 periph A */ + }; + + pinctrl_uart0_cts: uart0_cts-0 { + atmel,pins = + <0 21 0x1 0x0>; /* PA21 periph A */ + }; + }; + + uart1 { + pinctrl_uart1: uart1-0 { + atmel,pins = + <1 20 0x1 0x1 /* PB20 periph A with pullup */ + 1 21 0x1 0x0>; /* PB21 periph A */ + }; + + pinctrl_uart1_rts: uart1_rts-0 { + atmel,pins = + <1 24 0x1 0x0>; /* PB24 periph A */ + }; + + pinctrl_uart1_cts: uart1_cts-0 { + atmel,pins = + <1 26 0x1 0x0>; /* PB26 periph A */ + }; + + pinctrl_uart1_dtr_dsr: uart1_dtr_dsr-0 { + atmel,pins = + <1 19 0x1 0x0 /* PB19 periph A */ + 1 25 0x1 0x0>; /* PB25 periph A */ + }; + + pinctrl_uart1_dcd: uart1_dcd-0 { + atmel,pins = + <1 23 0x1 0x0>; /* PB23 periph A */ + }; + + pinctrl_uart1_ri: uart1_ri-0 { + atmel,pins = + <1 18 0x1 0x0>; /* PB18 periph A */ + }; + }; + + uart2 { + pinctrl_uart2: uart2-0 { + atmel,pins = + <0 22 0x1 0x0 /* PA22 periph A */ + 0 23 0x1 0x1>; /* PA23 periph A with pullup */ + }; + + pinctrl_uart2_rts: uart2_rts-0 { + atmel,pins = + <0 30 0x2 0x0>; /* PA30 periph B */ + }; + + pinctrl_uart2_cts: uart2_cts-0 { + atmel,pins = + <0 31 0x2 0x0>; /* PA31 periph B */ + }; + }; + + uart3 { + pinctrl_uart3: uart3-0 { + atmel,pins = + <0 5 0x2 0x1 /* PA5 periph B with pullup */ + 0 6 0x2 0x0>; /* PA6 periph B */ + }; + + pinctrl_uart3_rts: uart3_rts-0 { + atmel,pins = + <1 0 0x2 0x0>; /* PB0 periph B */ + }; + + pinctrl_uart3_cts: uart3_cts-0 { + atmel,pins = + <1 1 0x2 0x0>; /* PB1 periph B */ + }; + }; + + nand { + pinctrl_nand: nand-0 { + atmel,pins = + <2 2 0x0 0x1 /* PC2 gpio RDY pin pull_up */ + 1 1 0x0 0x1>; /* PB1 gpio CD pin pull_up */ + }; + }; + + pioA: gpio@fffff400 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff400 0x200>; + interrupts = <2 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioB: gpio@fffff600 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff600 0x200>; + interrupts = <3 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioC: gpio@fffff800 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff800 0x200>; + interrupts = <4 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioD: gpio@fffffa00 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffffa00 0x200>; + interrupts = <5 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + dbgu: serial@fffff200 { + compatible = "atmel,at91rm9200-usart"; + reg = <0xfffff200 0x200>; + interrupts = <1 4 7>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dbgu>; + status = "disabled"; + }; + + usart0: serial@fffc0000 { + compatible = "atmel,at91rm9200-usart"; + reg = <0xfffc0000 0x200>; + interrupts = <6 4 5>; + atmel,use-dma-rx; + atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + status = "disabled"; + }; + + usart1: serial@fffc4000 { + compatible = "atmel,at91rm9200-usart"; + reg = <0xfffc4000 0x200>; + interrupts = <7 4 5>; + atmel,use-dma-rx; + atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "disabled"; + }; + + usart2: serial@fffc8000 { + compatible = "atmel,at91rm9200-usart"; + reg = <0xfffc8000 0x200>; + interrupts = <8 4 5>; + atmel,use-dma-rx; + atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "disabled"; + }; + + usart3: serial@fffcc000 { + compatible = "atmel,at91rm9200-usart"; + reg = <0xfffcc000 0x200>; + interrupts = <23 4 5>; + atmel,use-dma-rx; + atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "disabled"; + }; + + usb1: gadget@fffb0000 { + compatible = "atmel,at91rm9200-udc"; + reg = <0xfffb0000 0x4000>; + interrupts = <11 4 2>; + status = "disabled"; + }; + }; + + nand0: nand@40000000 { + compatible = "atmel,at91rm9200-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40000000 0x10000000>; + atmel,nand-addr-offset = <21>; + atmel,nand-cmd-offset = <22>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_nand>; + nand-ecc-mode = "soft"; + gpios = <&pioC 2 0 + 0 + &pioB 1 0 + >; + status = "disabled"; + }; + + usb0: ohci@00300000 { + compatible = "atmel,at91rm9200-ohci", "usb-ohci"; + reg = <0x00300000 0x100000>; + interrupts = <23 4 2>; + status = "disabled"; + }; + }; + + i2c@0 { + compatible = "i2c-gpio"; + gpios = <&pioA 23 0 /* sda */ + &pioA 24 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; +}; diff --git a/arch/arm/boot/dts/at91rm9200ek.dts b/arch/arm/boot/dts/at91rm9200ek.dts new file mode 100644 index 0000000000000000000000000000000000000000..8aa48931e0a20b41685fbef3a972518ab4938c52 --- /dev/null +++ b/arch/arm/boot/dts/at91rm9200ek.dts @@ -0,0 +1,79 @@ +/* + * at91rm9200ek.dts - Device Tree file for Atmel AT91RM9200 evaluation kit + * + * Copyright (C) 2012 Joachim Eastwood + * + * Licensed under GPLv2 only + */ +/dts-v1/; +/include/ "at91rm9200.dtsi" + +/ { + model = "Atmel AT91RM9200 evaluation kit"; + compatible = "atmel,at91rm9200ek", "atmel,at91rm9200"; + + memory { + reg = <0x20000000 0x4000000>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + main_clock: clock@0 { + compatible = "atmel,osc", "fixed-clock"; + clock-frequency = <18432000>; + }; + }; + + ahb { + apb { + dbgu: serial@fffff200 { + status = "okay"; + }; + + usart1: serial@fffc4000 { + pinctrl-0 = + <&pinctrl_uart1 + &pinctrl_uart1_rts + &pinctrl_uart1_cts + &pinctrl_uart1_dtr_dsr + &pinctrl_uart1_dcd + &pinctrl_uart1_ri>; + status = "okay"; + }; + + usb1: gadget@fffb0000 { + atmel,vbus-gpio = <&pioD 4 0>; + status = "okay"; + }; + }; + + usb0: ohci@00300000 { + num-ports = <2>; + status = "okay"; + }; + }; + + leds { + compatible = "gpio-leds"; + + ds2 { + label = "green"; + gpios = <&pioB 0 0x1>; + linux,default-trigger = "mmc0"; + }; + + ds4 { + label = "yellow"; + gpios = <&pioB 1 0x1>; + linux,default-trigger = "heartbeat"; + }; + + ds6 { + label = "red"; + gpios = <&pioB 2 0x1>; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index d410581a5a859901b32a49a1f037356c9f22e294..b1d3fab60e0a9bf7df64de7cb1adcc45daaa95fa 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi @@ -21,8 +21,8 @@ serial2 = &usart1; serial3 = &usart2; serial4 = &usart3; - serial5 = &usart4; - serial6 = &usart5; + serial5 = &uart0; + serial6 = &uart1; gpio0 = &pioA; gpio1 = &pioB; gpio2 = &pioC; @@ -98,40 +98,250 @@ interrupts = <26 4 0 27 4 0 28 4 0>; }; - pioA: gpio@fffff400 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff400 0x100>; - interrupts = <2 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + pinctrl@fffff400 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + ranges = <0xfffff400 0xfffff400 0x600>; + + atmel,mux-mask = < + /* A B */ + 0xffffffff 0xffc00c3b /* pioA */ + 0xffffffff 0x7fff3ccf /* pioB */ + 0xffffffff 0x007fffff /* pioC */ + >; + + /* shared pinctrl settings */ + dbgu { + pinctrl_dbgu: dbgu-0 { + atmel,pins = + <1 14 0x1 0x0 /* PB14 periph A */ + 1 15 0x1 0x1>; /* PB15 periph with pullup */ + }; + }; - pioB: gpio@fffff600 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff600 0x100>; - interrupts = <3 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + usart0 { + pinctrl_usart0: usart0-0 { + atmel,pins = + <1 4 0x1 0x0 /* PB4 periph A */ + 1 5 0x1 0x0>; /* PB5 periph A */ + }; + + pinctrl_usart0_rts: usart0_rts-0 { + atmel,pins = + <1 26 0x1 0x0>; /* PB26 periph A */ + }; + + pinctrl_usart0_cts: usart0_cts-0 { + atmel,pins = + <1 27 0x1 0x0>; /* PB27 periph A */ + }; + + pinctrl_usart0_dtr_dsr: usart0_dtr_dsr-0 { + atmel,pins = + <1 24 0x1 0x0 /* PB24 periph A */ + 1 22 0x1 0x0>; /* PB22 periph A */ + }; + + pinctrl_usart0_dcd: usart0_dcd-0 { + atmel,pins = + <1 23 0x1 0x0>; /* PB23 periph A */ + }; + + pinctrl_usart0_ri: usart0_ri-0 { + atmel,pins = + <1 25 0x1 0x0>; /* PB25 periph A */ + }; + }; - pioC: gpio@fffff800 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff800 0x100>; - interrupts = <4 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; + usart1 { + pinctrl_usart1: usart1-0 { + atmel,pins = + <2 6 0x1 0x1 /* PB6 periph A with pullup */ + 2 7 0x1 0x0>; /* PB7 periph A */ + }; + + pinctrl_usart1_rts: usart1_rts-0 { + atmel,pins = + <1 28 0x1 0x0>; /* PB28 periph A */ + }; + + pinctrl_usart1_cts: usart1_cts-0 { + atmel,pins = + <1 29 0x1 0x0>; /* PB29 periph A */ + }; + }; + + usart2 { + pinctrl_usart2: usart2-0 { + atmel,pins = + <1 8 0x1 0x1 /* PB8 periph A with pullup */ + 1 9 0x1 0x0>; /* PB9 periph A */ + }; + + pinctrl_usart2_rts: usart2_rts-0 { + atmel,pins = + <0 4 0x1 0x0>; /* PA4 periph A */ + }; + + pinctrl_usart2_cts: usart2_cts-0 { + atmel,pins = + <0 5 0x1 0x0>; /* PA5 periph A */ + }; + }; + + usart3 { + pinctrl_usart3: usart3-0 { + atmel,pins = + <2 10 0x1 0x1 /* PB10 periph A with pullup */ + 2 11 0x1 0x0>; /* PB11 periph A */ + }; + + pinctrl_usart3_rts: usart3_rts-0 { + atmel,pins = + <3 8 0x2 0x0>; /* PB8 periph B */ + }; + + pinctrl_usart3_cts: usart3_cts-0 { + atmel,pins = + <3 10 0x2 0x0>; /* PB10 periph B */ + }; + }; + + uart0 { + pinctrl_uart0: uart0-0 { + atmel,pins = + <0 31 0x2 0x1 /* PA31 periph B with pullup */ + 0 30 0x2 0x0>; /* PA30 periph B */ + }; + }; + + uart1 { + pinctrl_uart1: uart1-0 { + atmel,pins = + <2 12 0x1 0x1 /* PB12 periph A with pullup */ + 2 13 0x1 0x0>; /* PB13 periph A */ + }; + }; + + nand { + pinctrl_nand: nand-0 { + atmel,pins = + <2 13 0x0 0x1 /* PC13 gpio RDY pin pull_up */ + 2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */ + }; + }; + + macb { + pinctrl_macb_rmii: macb_rmii-0 { + atmel,pins = + <0 12 0x1 0x0 /* PA12 periph A */ + 0 13 0x1 0x0 /* PA13 periph A */ + 0 14 0x1 0x0 /* PA14 periph A */ + 0 15 0x1 0x0 /* PA15 periph A */ + 0 16 0x1 0x0 /* PA16 periph A */ + 0 17 0x1 0x0 /* PA17 periph A */ + 0 18 0x1 0x0 /* PA18 periph A */ + 0 19 0x1 0x0 /* PA19 periph A */ + 0 20 0x1 0x0 /* PA20 periph A */ + 0 21 0x1 0x0>; /* PA21 periph A */ + }; + + pinctrl_macb_rmii_mii: macb_rmii_mii-0 { + atmel,pins = + <0 22 0x2 0x0 /* PA22 periph B */ + 0 23 0x2 0x0 /* PA23 periph B */ + 0 24 0x2 0x0 /* PA24 periph B */ + 0 25 0x2 0x0 /* PA25 periph B */ + 0 26 0x2 0x0 /* PA26 periph B */ + 0 27 0x2 0x0 /* PA27 periph B */ + 0 28 0x2 0x0 /* PA28 periph B */ + 0 29 0x2 0x0>; /* PA29 periph B */ + }; + + pinctrl_macb_rmii_mii_alt: macb_rmii_mii-1 { + atmel,pins = + <0 10 0x2 0x0 /* PA10 periph B */ + 0 11 0x2 0x0 /* PA11 periph B */ + 0 24 0x2 0x0 /* PA24 periph B */ + 0 25 0x2 0x0 /* PA25 periph B */ + 0 26 0x2 0x0 /* PA26 periph B */ + 0 27 0x2 0x0 /* PA27 periph B */ + 0 28 0x2 0x0 /* PA28 periph B */ + 0 29 0x2 0x0>; /* PA29 periph B */ + }; + }; + + mmc0 { + pinctrl_mmc0_clk: mmc0_clk-0 { + atmel,pins = + <0 8 0x1 0x0>; /* PA8 periph A */ + }; + + pinctrl_mmc0_slot0_cmd_dat0: mmc0_slot0_cmd_dat0-0 { + atmel,pins = + <0 7 0x1 0x1 /* PA7 periph A with pullup */ + 0 6 0x1 0x1>; /* PA6 periph A with pullup */ + }; + + pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 { + atmel,pins = + <0 9 0x1 0x1 /* PA9 periph A with pullup */ + 0 10 0x1 0x1 /* PA10 periph A with pullup */ + 0 11 0x1 0x1>; /* PA11 periph A with pullup */ + }; + + pinctrl_mmc0_slot1_cmd_dat0: mmc0_slot1_cmd_dat0-0 { + atmel,pins = + <0 1 0x2 0x1 /* PA1 periph B with pullup */ + 0 0 0x2 0x1>; /* PA0 periph B with pullup */ + }; + + pinctrl_mmc0_slot1_dat1_3: mmc0_slot1_dat1_3-0 { + atmel,pins = + <0 5 0x2 0x1 /* PA5 periph B with pullup */ + 0 4 0x2 0x1 /* PA4 periph B with pullup */ + 0 3 0x2 0x1>; /* PA3 periph B with pullup */ + }; + }; + + pioA: gpio@fffff400 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff400 0x200>; + interrupts = <2 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioB: gpio@fffff600 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff600 0x200>; + interrupts = <3 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioC: gpio@fffff800 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff800 0x200>; + interrupts = <4 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; }; dbgu: serial@fffff200 { compatible = "atmel,at91sam9260-usart"; reg = <0xfffff200 0x200>; interrupts = <1 4 7>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dbgu>; status = "disabled"; }; @@ -141,6 +351,8 @@ interrupts = <6 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart0>; status = "disabled"; }; @@ -150,6 +362,8 @@ interrupts = <7 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart1>; status = "disabled"; }; @@ -159,6 +373,8 @@ interrupts = <8 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart2>; status = "disabled"; }; @@ -168,24 +384,30 @@ interrupts = <23 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart3>; status = "disabled"; }; - usart4: serial@fffd4000 { + uart0: serial@fffd4000 { compatible = "atmel,at91sam9260-usart"; reg = <0xfffd4000 0x200>; interrupts = <24 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; status = "disabled"; }; - usart5: serial@fffd8000 { + uart1: serial@fffd8000 { compatible = "atmel,at91sam9260-usart"; reg = <0xfffd8000 0x200>; interrupts = <25 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; status = "disabled"; }; @@ -193,6 +415,8 @@ compatible = "cdns,at32ap7000-macb", "cdns,macb"; reg = <0xfffc4000 0x100>; interrupts = <21 4 3>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb_rmii>; status = "disabled"; }; @@ -212,6 +436,15 @@ status = "disabled"; }; + mmc0: mmc@fffa8000 { + compatible = "atmel,hsmci"; + reg = <0xfffa8000 0x600>; + interrupts = <9 4 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + adc0: adc@fffe0000 { compatible = "atmel,at91sam9260-adc"; reg = <0xfffe0000 0x100>; @@ -257,6 +490,8 @@ >; atmel,nand-addr-offset = <21>; atmel,nand-cmd-offset = <22>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_nand>; gpios = <&pioC 13 0 &pioC 14 0 0 diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi index 3e6e5c1abbf37184a44237e464080a52f4312e9f..66106eecf1ed9e912ae6b34ad90085f698837559 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/at91sam9263.dtsi @@ -89,60 +89,243 @@ reg = <0xfffffd10 0x10>; }; - pioA: gpio@fffff200 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff200 0x100>; - interrupts = <2 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + pinctrl@fffff200 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + ranges = <0xfffff200 0xfffff200 0xa00>; - pioB: gpio@fffff400 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff400 0x100>; - interrupts = <3 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + atmel,mux-mask = < + /* A B */ + 0xfffffffb 0xffffe07f /* pioA */ + 0x0007ffff 0x39072fff /* pioB */ + 0xffffffff 0x3ffffff8 /* pioC */ + 0xfffffbff 0xffffffff /* pioD */ + 0xffe00fff 0xfbfcff00 /* pioE */ + >; - pioC: gpio@fffff600 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff600 0x100>; - interrupts = <4 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + /* shared pinctrl settings */ + dbgu { + pinctrl_dbgu: dbgu-0 { + atmel,pins = + <2 30 0x1 0x0 /* PC30 periph A */ + 2 31 0x1 0x1>; /* PC31 periph with pullup */ + }; + }; - pioD: gpio@fffff800 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff800 0x100>; - interrupts = <4 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + usart0 { + pinctrl_usart0: usart0-0 { + atmel,pins = + <0 26 0x1 0x1 /* PA26 periph A with pullup */ + 0 27 0x1 0x0>; /* PA27 periph A */ + }; - pioE: gpio@fffffa00 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffffa00 0x100>; - interrupts = <4 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; + pinctrl_usart0_rts: usart0_rts-0 { + atmel,pins = + <0 28 0x1 0x0>; /* PA28 periph A */ + }; + + pinctrl_usart0_cts: usart0_cts-0 { + atmel,pins = + <0 29 0x1 0x0>; /* PA29 periph A */ + }; + }; + + usart1 { + pinctrl_usart1: usart1-0 { + atmel,pins = + <3 0 0x1 0x1 /* PD0 periph A with pullup */ + 3 1 0x1 0x0>; /* PD1 periph A */ + }; + + pinctrl_usart1_rts: usart1_rts-0 { + atmel,pins = + <3 7 0x2 0x0>; /* PD7 periph B */ + }; + + pinctrl_usart1_cts: usart1_cts-0 { + atmel,pins = + <3 8 0x2 0x0>; /* PD8 periph B */ + }; + }; + + usart2 { + pinctrl_usart2: usart2-0 { + atmel,pins = + <3 2 0x1 0x1 /* PD2 periph A with pullup */ + 3 3 0x1 0x0>; /* PD3 periph A */ + }; + + pinctrl_usart2_rts: usart2_rts-0 { + atmel,pins = + <3 5 0x2 0x0>; /* PD5 periph B */ + }; + + pinctrl_usart2_cts: usart2_cts-0 { + atmel,pins = + <4 6 0x2 0x0>; /* PD6 periph B */ + }; + }; + + nand { + pinctrl_nand: nand-0 { + atmel,pins = + <0 22 0x0 0x1 /* PA22 gpio RDY pin pull_up*/ + 3 15 0x0 0x1>; /* PD15 gpio enable pin pull_up */ + }; + }; + + macb { + pinctrl_macb_rmii: macb_rmii-0 { + atmel,pins = + <2 25 0x2 0x0 /* PC25 periph B */ + 4 21 0x1 0x0 /* PE21 periph A */ + 4 23 0x1 0x0 /* PE23 periph A */ + 4 24 0x1 0x0 /* PE24 periph A */ + 4 25 0x1 0x0 /* PE25 periph A */ + 4 26 0x1 0x0 /* PE26 periph A */ + 4 27 0x1 0x0 /* PE27 periph A */ + 4 28 0x1 0x0 /* PE28 periph A */ + 4 29 0x1 0x0 /* PE29 periph A */ + 4 30 0x1 0x0>; /* PE30 periph A */ + }; + + pinctrl_macb_rmii_mii: macb_rmii_mii-0 { + atmel,pins = + <2 20 0x2 0x0 /* PC20 periph B */ + 2 21 0x2 0x0 /* PC21 periph B */ + 2 22 0x2 0x0 /* PC22 periph B */ + 2 23 0x2 0x0 /* PC23 periph B */ + 2 24 0x2 0x0 /* PC24 periph B */ + 2 25 0x2 0x0 /* PC25 periph B */ + 2 27 0x2 0x0 /* PC27 periph B */ + 4 22 0x2 0x0>; /* PE22 periph B */ + }; + }; + + mmc0 { + pinctrl_mmc0_clk: mmc0_clk-0 { + atmel,pins = + <0 12 0x1 0x0>; /* PA12 periph A */ + }; + + pinctrl_mmc0_slot0_cmd_dat0: mmc0_slot0_cmd_dat0-0 { + atmel,pins = + <0 1 0x1 0x1 /* PA1 periph A with pullup */ + 0 0 0x1 0x1>; /* PA0 periph A with pullup */ + }; + + pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 { + atmel,pins = + <0 3 0x1 0x1 /* PA3 periph A with pullup */ + 0 4 0x1 0x1 /* PA4 periph A with pullup */ + 0 5 0x1 0x1>; /* PA5 periph A with pullup */ + }; + + pinctrl_mmc0_slot1_cmd_dat0: mmc0_slot1_cmd_dat0-0 { + atmel,pins = + <0 16 0x1 0x1 /* PA16 periph A with pullup */ + 0 17 0x1 0x1>; /* PA17 periph A with pullup */ + }; + + pinctrl_mmc0_slot1_dat1_3: mmc0_slot1_dat1_3-0 { + atmel,pins = + <0 18 0x1 0x1 /* PA18 periph A with pullup */ + 0 19 0x1 0x1 /* PA19 periph A with pullup */ + 0 20 0x1 0x1>; /* PA20 periph A with pullup */ + }; + }; + + mmc1 { + pinctrl_mmc1_clk: mmc1_clk-0 { + atmel,pins = + <0 6 0x1 0x0>; /* PA6 periph A */ + }; + + pinctrl_mmc1_slot0_cmd_dat0: mmc1_slot0_cmd_dat0-0 { + atmel,pins = + <0 7 0x1 0x1 /* PA7 periph A with pullup */ + 0 8 0x1 0x1>; /* PA8 periph A with pullup */ + }; + + pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 { + atmel,pins = + <0 9 0x1 0x1 /* PA9 periph A with pullup */ + 0 10 0x1 0x1 /* PA10 periph A with pullup */ + 0 11 0x1 0x1>; /* PA11 periph A with pullup */ + }; + + pinctrl_mmc1_slot1_cmd_dat0: mmc1_slot1_cmd_dat0-0 { + atmel,pins = + <0 21 0x1 0x1 /* PA21 periph A with pullup */ + 0 22 0x1 0x1>; /* PA22 periph A with pullup */ + }; + + pinctrl_mmc1_slot1_dat1_3: mmc1_slot1_dat1_3-0 { + atmel,pins = + <0 23 0x1 0x1 /* PA23 periph A with pullup */ + 0 24 0x1 0x1 /* PA24 periph A with pullup */ + 0 25 0x1 0x1>; /* PA25 periph A with pullup */ + }; + }; + + pioA: gpio@fffff200 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff200 0x200>; + interrupts = <2 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioB: gpio@fffff400 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff400 0x200>; + interrupts = <3 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioC: gpio@fffff600 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff600 0x200>; + interrupts = <4 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioD: gpio@fffff800 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff800 0x200>; + interrupts = <4 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioE: gpio@fffffa00 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffffa00 0x200>; + interrupts = <4 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; }; dbgu: serial@ffffee00 { compatible = "atmel,at91sam9260-usart"; reg = <0xffffee00 0x200>; interrupts = <1 4 7>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dbgu>; status = "disabled"; }; @@ -152,6 +335,8 @@ interrupts = <7 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart0>; status = "disabled"; }; @@ -161,6 +346,8 @@ interrupts = <8 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart1>; status = "disabled"; }; @@ -170,6 +357,8 @@ interrupts = <9 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart2>; status = "disabled"; }; @@ -177,6 +366,8 @@ compatible = "cdns,at32ap7000-macb", "cdns,macb"; reg = <0xfffbc000 0x100>; interrupts = <21 4 3>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb_rmii>; status = "disabled"; }; @@ -195,6 +386,24 @@ #size-cells = <0>; status = "disabled"; }; + + mmc0: mmc@fff80000 { + compatible = "atmel,hsmci"; + reg = <0xfff80000 0x600>; + interrupts = <10 4 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + mmc1: mmc@fff84000 { + compatible = "atmel,hsmci"; + reg = <0xfff84000 0x600>; + interrupts = <11 4 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; nand0: nand@40000000 { @@ -206,6 +415,8 @@ >; atmel,nand-addr-offset = <21>; atmel,nand-cmd-offset = <22>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_nand>; gpios = <&pioA 22 0 &pioD 15 0 0 diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts index f86ac4b609fc108c0f1ad757c4a254dc6aec18d3..1eb08728f5279090a3f2ba704b35f47f1ef0fbe6 100644 --- a/arch/arm/boot/dts/at91sam9263ek.dts +++ b/arch/arm/boot/dts/at91sam9263ek.dts @@ -38,6 +38,10 @@ }; usart0: serial@fff8c000 { + pinctrl-0 = < + &pinctrl_usart0 + &pinctrl_usart0_rts + &pinctrl_usart0_cts>; status = "okay"; }; @@ -50,6 +54,31 @@ atmel,vbus-gpio = <&pioA 25 0>; status = "okay"; }; + + mmc0: mmc@fff80000 { + pinctrl-0 = < + &pinctrl_board_mmc0 + &pinctrl_mmc0_clk + &pinctrl_mmc0_slot0_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioE 18 0>; + wp-gpios = <&pioE 19 0>; + }; + }; + + pinctrl@fffff200 { + mmc0 { + pinctrl_board_mmc0: mmc0-board { + atmel,pins = + <5 18 0x0 0x5 /* PE18 gpio CD pin pull up and deglitch */ + 5 19 0x0 0x1>; /* PE19 gpio WP pin pull up */ + }; + }; + }; }; nand0: nand@40000000 { diff --git a/arch/arm/boot/dts/at91sam9g15.dtsi b/arch/arm/boot/dts/at91sam9g15.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..fbe7a7089c2adbc82da7d3ef995b6506c1089d1d --- /dev/null +++ b/arch/arm/boot/dts/at91sam9g15.dtsi @@ -0,0 +1,28 @@ +/* + * at91sam9g15.dtsi - Device Tree Include file for AT91SAM9G15 SoC + * + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2. + */ + +/include/ "at91sam9x5.dtsi" + +/ { + model = "Atmel AT91SAM9G15 SoC"; + compatible = "atmel, at91sam9g15, atmel,at91sam9x5"; + + ahb { + apb { + pinctrl@fffff400 { + atmel,mux-mask = < + /* A B C */ + 0xffffffff 0xffe0399f 0x00000000 /* pioA */ + 0x00040000 0x00047e3f 0x00000000 /* pioB */ + 0xfdffffff 0x00000000 0xb83fffff /* pioC */ + 0x003fffff 0x003f8000 0x00000000 /* pioD */ + >; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91sam9g15ek.dts b/arch/arm/boot/dts/at91sam9g15ek.dts new file mode 100644 index 0000000000000000000000000000000000000000..86dd3f6d938ff272334102894fd4e2d9e17c4457 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9g15ek.dts @@ -0,0 +1,16 @@ +/* + * at91sam9g15ek.dts - Device Tree file for AT91SAM9G15-EK board + * + * Copyright (C) 2012 Atmel, + * 2012 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ +/dts-v1/; +/include/ "at91sam9g15.dtsi" +/include/ "at91sam9x5ek.dtsi" + +/ { + model = "Atmel AT91SAM9G25-EK"; + compatible = "atmel,at91sam9g15ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; +}; diff --git a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts index f1b2e148ac8cd679be6e3b00f6b9b0c1d65aedc8..66467b1131264bd409da608f58d70f5f3703f79e 100644 --- a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts +++ b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts @@ -12,6 +12,32 @@ model = "Atmel at91sam9g20ek 2 mmc"; compatible = "atmel,at91sam9g20ek_2mmc", "atmel,at91sam9g20", "atmel,at91sam9"; + ahb { + apb{ + mmc0: mmc@fffa8000 { + /* clk already mux wuth slot0 */ + pinctrl-0 = < + &pinctrl_board_mmc0_slot0 + &pinctrl_mmc0_slot0_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioC 2 0>; + }; + }; + + pinctrl@fffff400 { + mmc0_slot0 { + pinctrl_board_mmc0_slot0: mmc0_slot0-board { + atmel,pins = + <2 2 0x0 0x5>; /* PC2 gpio CD pin pull up and deglitch */ + }; + }; + }; + }; + }; + leds { compatible = "gpio-leds"; diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi index e6391a4e6649cc3787ba14d7ed1d190b2d932964..32a500a0e481f7473de51be152546081b8bddd15 100644 --- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi @@ -35,6 +35,13 @@ }; usart0: serial@fffb0000 { + pinctrl-0 = + <&pinctrl_usart0 + &pinctrl_usart0_rts + &pinctrl_usart0_cts + &pinctrl_usart0_dtr_dsr + &pinctrl_usart0_dcd + &pinctrl_usart0_ri>; status = "okay"; }; @@ -51,6 +58,29 @@ atmel,vbus-gpio = <&pioC 5 0>; status = "okay"; }; + + mmc0: mmc@fffa8000 { + pinctrl-0 = < + &pinctrl_board_mmc0_slot1 + &pinctrl_mmc0_clk + &pinctrl_mmc0_slot1_cmd_dat0 + &pinctrl_mmc0_slot1_dat1_3>; + status = "okay"; + slot@1 { + reg = <1>; + bus-width = <4>; + cd-gpios = <&pioC 9 0>; + }; + }; + + pinctrl@fffff400 { + mmc0_slot1 { + pinctrl_board_mmc0_slot1: mmc0_slot1-board { + atmel,pins = + <2 9 0x0 0x5>; /* PC9 gpio CD pin pull up and deglitch */ + }; + }; + }; }; nand0: nand@40000000 { diff --git a/arch/arm/boot/dts/at91sam9g25.dtsi b/arch/arm/boot/dts/at91sam9g25.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..05a718fb83c49b4cfa1fcb35be13b4e9ff2d2ec6 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9g25.dtsi @@ -0,0 +1,28 @@ +/* + * at91sam9g25.dtsi - Device Tree Include file for AT91SAM9G25 SoC + * + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2. + */ + +/include/ "at91sam9x5.dtsi" + +/ { + model = "Atmel AT91SAM9G25 SoC"; + compatible = "atmel, at91sam9g25, atmel,at91sam9x5"; + + ahb { + apb { + pinctrl@fffff400 { + atmel,mux-mask = < + /* A B C */ + 0xffffffff 0xffe0399f 0xc000001c /* pioA */ + 0x0007ffff 0x8000fe3f 0x00000000 /* pioB */ + 0x80000000 0x07c0ffff 0xb83fffff /* pioC */ + 0x003fffff 0x003f8000 0x00000000 /* pioD */ + >; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts index 877c08f06763c643362eb41b8ebd058ac85abf7d..c5ab16fba059421730a212593a69ae6cd47acddc 100644 --- a/arch/arm/boot/dts/at91sam9g25ek.dts +++ b/arch/arm/boot/dts/at91sam9g25ek.dts @@ -7,55 +7,10 @@ * Licensed under GPLv2 or later. */ /dts-v1/; -/include/ "at91sam9x5.dtsi" -/include/ "at91sam9x5cm.dtsi" +/include/ "at91sam9g25.dtsi" +/include/ "at91sam9x5ek.dtsi" / { model = "Atmel AT91SAM9G25-EK"; compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; - - chosen { - bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"; - }; - - ahb { - apb { - dbgu: serial@fffff200 { - status = "okay"; - }; - - usart0: serial@f801c000 { - status = "okay"; - }; - - macb0: ethernet@f802c000 { - phy-mode = "rmii"; - status = "okay"; - }; - - i2c0: i2c@f8010000 { - status = "okay"; - }; - - i2c1: i2c@f8014000 { - status = "okay"; - }; - - i2c2: i2c@f8018000 { - status = "okay"; - }; - }; - - usb0: ohci@00600000 { - status = "okay"; - num-ports = <2>; - atmel,vbus-gpio = <&pioD 19 1 - &pioD 20 1 - >; - }; - - usb1: ehci@00700000 { - status = "okay"; - }; - }; }; diff --git a/arch/arm/boot/dts/at91sam9g35.dtsi b/arch/arm/boot/dts/at91sam9g35.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..f9d14a722794eb0f927ecb03eeac0d790f0efff7 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9g35.dtsi @@ -0,0 +1,28 @@ +/* + * at91sam9g35.dtsi - Device Tree Include file for AT91SAM9G35 SoC + * + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2. + */ + +/include/ "at91sam9x5.dtsi" + +/ { + model = "Atmel AT91SAM9G35 SoC"; + compatible = "atmel, at91sam9g35, atmel,at91sam9x5"; + + ahb { + apb { + pinctrl@fffff400 { + atmel,mux-mask = < + /* A B C */ + 0xffffffff 0xffe0399f 0xc000000c /* pioA */ + 0x000406ff 0x00047e3f 0x00000000 /* pioB */ + 0xfdffffff 0x00000000 0xb83fffff /* pioC */ + 0x003fffff 0x003f8000 0x00000000 /* pioD */ + >; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts new file mode 100644 index 0000000000000000000000000000000000000000..95944bdd798dc2db4a8d0d1d1d2d25740e461ca1 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9g35ek.dts @@ -0,0 +1,16 @@ +/* + * at91sam9g35ek.dts - Device Tree file for AT91SAM9G35-EK board + * + * Copyright (C) 2012 Atmel, + * 2012 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ +/dts-v1/; +/include/ "at91sam9g35.dtsi" +/include/ "at91sam9x5ek.dtsi" + +/ { + model = "Atmel AT91SAM9G35-EK"; + compatible = "atmel,at91sam9g35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; +}; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 3add030d61f8651fcf5a0476b11423897de71560..0741caeeced1a5618950e1c9a299578ad2b2ba3d 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -108,60 +108,243 @@ interrupts = <21 4 0>; }; - pioA: gpio@fffff200 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff200 0x100>; - interrupts = <2 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + pinctrl@fffff200 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + ranges = <0xfffff200 0xfffff200 0xa00>; + + atmel,mux-mask = < + /* A B */ + 0xffffffff 0xffc003ff /* pioA */ + 0xffffffff 0x800f8f00 /* pioB */ + 0xffffffff 0x00000e00 /* pioC */ + 0xffffffff 0xff0c1381 /* pioD */ + 0xffffffff 0x81ffff81 /* pioE */ + >; + + /* shared pinctrl settings */ + dbgu { + pinctrl_dbgu: dbgu-0 { + atmel,pins = + <1 12 0x1 0x0 /* PB12 periph A */ + 1 13 0x1 0x0>; /* PB13 periph A */ + }; + }; - pioB: gpio@fffff400 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff400 0x100>; - interrupts = <3 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + usart0 { + pinctrl_usart0: usart0-0 { + atmel,pins = + <1 19 0x1 0x1 /* PB19 periph A with pullup */ + 1 18 0x1 0x0>; /* PB18 periph A */ + }; + + pinctrl_usart0_rts: usart0_rts-0 { + atmel,pins = + <1 17 0x2 0x0>; /* PB17 periph B */ + }; + + pinctrl_usart0_cts: usart0_cts-0 { + atmel,pins = + <1 15 0x2 0x0>; /* PB15 periph B */ + }; + }; - pioC: gpio@fffff600 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff600 0x100>; - interrupts = <4 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + uart1 { + pinctrl_usart1: usart1-0 { + atmel,pins = + <1 4 0x1 0x1 /* PB4 periph A with pullup */ + 1 5 0x1 0x0>; /* PB5 periph A */ + }; + + pinctrl_usart1_rts: usart1_rts-0 { + atmel,pins = + <3 16 0x1 0x0>; /* PD16 periph A */ + }; + + pinctrl_usart1_cts: usart1_cts-0 { + atmel,pins = + <3 17 0x1 0x0>; /* PD17 periph A */ + }; + }; - pioD: gpio@fffff800 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffff800 0x100>; - interrupts = <5 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + usart2 { + pinctrl_usart2: usart2-0 { + atmel,pins = + <1 6 0x1 0x1 /* PB6 periph A with pullup */ + 1 7 0x1 0x0>; /* PB7 periph A */ + }; + + pinctrl_usart2_rts: usart2_rts-0 { + atmel,pins = + <2 9 0x2 0x0>; /* PC9 periph B */ + }; + + pinctrl_usart2_cts: usart2_cts-0 { + atmel,pins = + <2 11 0x2 0x0>; /* PC11 periph B */ + }; + }; - pioE: gpio@fffffa00 { - compatible = "atmel,at91rm9200-gpio"; - reg = <0xfffffa00 0x100>; - interrupts = <5 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; + usart3 { + pinctrl_usart3: usart3-0 { + atmel,pins = + <1 8 0x1 0x1 /* PB9 periph A with pullup */ + 1 9 0x1 0x0>; /* PB8 periph A */ + }; + + pinctrl_usart3_rts: usart3_rts-0 { + atmel,pins = + <0 23 0x2 0x0>; /* PA23 periph B */ + }; + + pinctrl_usart3_cts: usart3_cts-0 { + atmel,pins = + <0 24 0x2 0x0>; /* PA24 periph B */ + }; + }; + + nand { + pinctrl_nand: nand-0 { + atmel,pins = + <2 8 0x0 0x1 /* PC8 gpio RDY pin pull_up*/ + 2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */ + }; + }; + + macb { + pinctrl_macb_rmii: macb_rmii-0 { + atmel,pins = + <0 10 0x1 0x0 /* PA10 periph A */ + 0 11 0x1 0x0 /* PA11 periph A */ + 0 12 0x1 0x0 /* PA12 periph A */ + 0 13 0x1 0x0 /* PA13 periph A */ + 0 14 0x1 0x0 /* PA14 periph A */ + 0 15 0x1 0x0 /* PA15 periph A */ + 0 16 0x1 0x0 /* PA16 periph A */ + 0 17 0x1 0x0 /* PA17 periph A */ + 0 18 0x1 0x0 /* PA18 periph A */ + 0 19 0x1 0x0>; /* PA19 periph A */ + }; + + pinctrl_macb_rmii_mii: macb_rmii_mii-0 { + atmel,pins = + <0 6 0x2 0x0 /* PA6 periph B */ + 0 7 0x2 0x0 /* PA7 periph B */ + 0 8 0x2 0x0 /* PA8 periph B */ + 0 9 0x2 0x0 /* PA9 periph B */ + 0 27 0x2 0x0 /* PA27 periph B */ + 0 28 0x2 0x0 /* PA28 periph B */ + 0 29 0x2 0x0 /* PA29 periph B */ + 0 30 0x2 0x0>; /* PA30 periph B */ + }; + }; + + mmc0 { + pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 { + atmel,pins = + <0 0 0x1 0x0 /* PA0 periph A */ + 0 1 0x1 0x1 /* PA1 periph A with pullup */ + 0 2 0x1 0x1>; /* PA2 periph A with pullup */ + }; + + pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 { + atmel,pins = + <0 3 0x1 0x1 /* PA3 periph A with pullup */ + 0 4 0x1 0x1 /* PA4 periph A with pullup */ + 0 5 0x1 0x1>; /* PA5 periph A with pullup */ + }; + + pinctrl_mmc0_slot0_dat4_7: mmc0_slot0_dat4_7-0 { + atmel,pins = + <0 6 0x1 0x1 /* PA6 periph A with pullup */ + 0 7 0x1 0x1 /* PA7 periph A with pullup */ + 0 8 0x1 0x1 /* PA8 periph A with pullup */ + 0 9 0x1 0x1>; /* PA9 periph A with pullup */ + }; + }; + + mmc1 { + pinctrl_mmc1_slot0_clk_cmd_dat0: mmc1_slot0_clk_cmd_dat0-0 { + atmel,pins = + <0 31 0x1 0x0 /* PA31 periph A */ + 0 22 0x1 0x1 /* PA22 periph A with pullup */ + 0 23 0x1 0x1>; /* PA23 periph A with pullup */ + }; + + pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 { + atmel,pins = + <0 24 0x1 0x1 /* PA24 periph A with pullup */ + 0 25 0x1 0x1 /* PA25 periph A with pullup */ + 0 26 0x1 0x1>; /* PA26 periph A with pullup */ + }; + + pinctrl_mmc1_slot0_dat4_7: mmc1_slot0_dat4_7-0 { + atmel,pins = + <0 27 0x1 0x1 /* PA27 periph A with pullup */ + 0 28 0x1 0x1 /* PA28 periph A with pullup */ + 0 29 0x1 0x1 /* PA29 periph A with pullup */ + 0 20 0x1 0x1>; /* PA30 periph A with pullup */ + }; + }; + + pioA: gpio@fffff200 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff200 0x200>; + interrupts = <2 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioB: gpio@fffff400 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff400 0x200>; + interrupts = <3 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioC: gpio@fffff600 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff600 0x200>; + interrupts = <4 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioD: gpio@fffff800 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffff800 0x200>; + interrupts = <5 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioE: gpio@fffffa00 { + compatible = "atmel,at91rm9200-gpio"; + reg = <0xfffffa00 0x200>; + interrupts = <5 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; }; dbgu: serial@ffffee00 { compatible = "atmel,at91sam9260-usart"; reg = <0xffffee00 0x200>; interrupts = <1 4 7>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dbgu>; status = "disabled"; }; @@ -171,6 +354,8 @@ interrupts = <7 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart0>; status = "disabled"; }; @@ -180,6 +365,8 @@ interrupts = <8 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart1>; status = "disabled"; }; @@ -189,6 +376,8 @@ interrupts = <9 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart2>; status = "disabled"; }; @@ -198,6 +387,8 @@ interrupts = <10 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart3>; status = "disabled"; }; @@ -205,6 +396,8 @@ compatible = "cdns,at32ap7000-macb", "cdns,macb"; reg = <0xfffbc000 0x100>; interrupts = <25 4 3>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb_rmii>; status = "disabled"; }; @@ -262,6 +455,24 @@ trigger-value = <0x6>; }; }; + + mmc0: mmc@fff80000 { + compatible = "atmel,hsmci"; + reg = <0xfff80000 0x600>; + interrupts = <11 4 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + mmc1: mmc@fffd0000 { + compatible = "atmel,hsmci"; + reg = <0xfffd0000 0x600>; + interrupts = <29 4 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; nand0: nand@40000000 { @@ -273,6 +484,8 @@ >; atmel,nand-addr-offset = <21>; atmel,nand-cmd-offset = <22>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_nand>; gpios = <&pioC 8 0 &pioC 14 0 0 diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index 15e1dd43f625aee627438c302e9a4a13f7002031..20c31913c27015ff21086a6fcede5883dcaff0bb 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -39,6 +39,10 @@ }; usart1: serial@fff90000 { + pinctrl-0 = + <&pinctrl_usart1 + &pinctrl_usart1_rts + &pinctrl_usart1_cts>; status = "okay"; }; @@ -54,6 +58,50 @@ i2c1: i2c@fff88000 { status = "okay"; }; + + mmc0: mmc@fff80000 { + pinctrl-0 = < + &pinctrl_board_mmc0 + &pinctrl_mmc0_slot0_clk_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 10 0>; + }; + }; + + mmc1: mmc@fffd0000 { + pinctrl-0 = < + &pinctrl_board_mmc1 + &pinctrl_mmc1_slot0_clk_cmd_dat0 + &pinctrl_mmc1_slot0_dat1_3>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 11 0>; + wp-gpios = <&pioD 29 0>; + }; + }; + + pinctrl@fffff200 { + mmc0 { + pinctrl_board_mmc0: mmc0-board { + atmel,pins = + <3 10 0x0 0x5>; /* PD10 gpio CD pin pull up and deglitch */ + }; + }; + + mmc1 { + pinctrl_board_mmc1: mmc1-board { + atmel,pins = + <3 11 0x0 0x5 /* PD11 gpio CD pin pull up and deglitch */ + 3 29 0x0 0x1>; /* PD29 gpio WP pin pull up */ + }; + }; + }; }; nand0: nand@40000000 { diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi index 82508d68aa7edb0cdc98c5245d7872d47720dfd9..e9efb34f437983370649fa096c006fe1638c1e01 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/at91sam9n12.dtsi @@ -84,6 +84,15 @@ reg = <0xfffffe10 0x10>; }; + mmc0: mmc@f0008000 { + compatible = "atmel,hsmci"; + reg = <0xf0008000 0x600>; + interrupts = <12 4 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + tcb0: timer@f8008000 { compatible = "atmel,at91sam9x5-tcb"; reg = <0xf8008000 0x100>; @@ -102,50 +111,186 @@ interrupts = <20 4 0>; }; - pioA: gpio@fffff400 { - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; - reg = <0xfffff400 0x100>; - interrupts = <2 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + pinctrl@fffff400 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus"; + ranges = <0xfffff400 0xfffff400 0x800>; - pioB: gpio@fffff600 { - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; - reg = <0xfffff600 0x100>; - interrupts = <2 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + atmel,mux-mask = < + /* A B C */ + 0xffffffff 0xffe07983 0x00000000 /* pioA */ + 0x00040000 0x00047e0f 0x00000000 /* pioB */ + 0xfdffffff 0x07c00000 0xb83fffff /* pioC */ + 0x003fffff 0x003f8000 0x00000000 /* pioD */ + >; - pioC: gpio@fffff800 { - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; - reg = <0xfffff800 0x100>; - interrupts = <3 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + /* shared pinctrl settings */ + dbgu { + pinctrl_dbgu: dbgu-0 { + atmel,pins = + <0 9 0x1 0x0 /* PA9 periph A */ + 0 10 0x1 0x1>; /* PA10 periph with pullup */ + }; + }; - pioD: gpio@fffffa00 { - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; - reg = <0xfffffa00 0x100>; - interrupts = <3 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; + usart0 { + pinctrl_usart0: usart0-0 { + atmel,pins = + <0 1 0x1 0x1 /* PA1 periph A with pullup */ + 0 0 0x1 0x0>; /* PA0 periph A */ + }; + + pinctrl_usart0_rts: usart0_rts-0 { + atmel,pins = + <0 2 0x1 0x0>; /* PA2 periph A */ + }; + + pinctrl_usart0_cts: usart0_cts-0 { + atmel,pins = + <0 3 0x1 0x0>; /* PA3 periph A */ + }; + }; + + usart1 { + pinctrl_usart1: usart1-0 { + atmel,pins = + <0 6 0x1 0x1 /* PA6 periph A with pullup */ + 0 5 0x1 0x0>; /* PA5 periph A */ + }; + }; + + usart2 { + pinctrl_usart2: usart2-0 { + atmel,pins = + <0 8 0x1 0x1 /* PA8 periph A with pullup */ + 0 7 0x1 0x0>; /* PA7 periph A */ + }; + + pinctrl_usart2_rts: usart2_rts-0 { + atmel,pins = + <1 0 0x2 0x0>; /* PB0 periph B */ + }; + + pinctrl_usart2_cts: usart2_cts-0 { + atmel,pins = + <1 1 0x2 0x0>; /* PB1 periph B */ + }; + }; + + usart3 { + pinctrl_usart3: usart3-0 { + atmel,pins = + <2 23 0x2 0x1 /* PC23 periph B with pullup */ + 2 22 0x2 0x0>; /* PC22 periph B */ + }; + + pinctrl_usart3_rts: usart3_rts-0 { + atmel,pins = + <2 24 0x2 0x0>; /* PC24 periph B */ + }; + + pinctrl_usart3_cts: usart3_cts-0 { + atmel,pins = + <2 25 0x2 0x0>; /* PC25 periph B */ + }; + }; + + uart0 { + pinctrl_uart0: uart0-0 { + atmel,pins = + <2 9 0x3 0x1 /* PC9 periph C with pullup */ + 2 8 0x3 0x0>; /* PC8 periph C */ + }; + }; + + uart1 { + pinctrl_uart1: uart1-0 { + atmel,pins = + <2 16 0x3 0x1 /* PC17 periph C with pullup */ + 2 17 0x3 0x0>; /* PC16 periph C */ + }; + }; + + nand { + pinctrl_nand: nand-0 { + atmel,pins = + <3 5 0x0 0x1 /* PD5 gpio RDY pin pull_up*/ + 3 4 0x0 0x1>; /* PD4 gpio enable pin pull_up */ + }; + }; + + mmc0 { + pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 { + atmel,pins = + <0 17 0x1 0x0 /* PA17 periph A */ + 0 16 0x1 0x1 /* PA16 periph A with pullup */ + 0 15 0x1 0x1>; /* PA15 periph A with pullup */ + }; + + pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 { + atmel,pins = + <0 18 0x1 0x1 /* PA18 periph A with pullup */ + 0 19 0x1 0x1 /* PA19 periph A with pullup */ + 0 20 0x1 0x1>; /* PA20 periph A with pullup */ + }; + + pinctrl_mmc0_slot0_dat4_7: mmc0_slot0_dat4_7-0 { + atmel,pins = + <0 11 0x2 0x1 /* PA11 periph B with pullup */ + 0 12 0x2 0x1 /* PA12 periph B with pullup */ + 0 13 0x2 0x1 /* PA13 periph B with pullup */ + 0 14 0x2 0x1>; /* PA14 periph B with pullup */ + }; + }; + + pioA: gpio@fffff400 { + compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + reg = <0xfffff400 0x200>; + interrupts = <2 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioB: gpio@fffff600 { + compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + reg = <0xfffff600 0x200>; + interrupts = <2 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioC: gpio@fffff800 { + compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + reg = <0xfffff800 0x200>; + interrupts = <3 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioD: gpio@fffffa00 { + compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + reg = <0xfffffa00 0x200>; + interrupts = <3 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; }; dbgu: serial@fffff200 { compatible = "atmel,at91sam9260-usart"; reg = <0xfffff200 0x200>; interrupts = <1 4 7>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dbgu>; status = "disabled"; }; @@ -155,6 +300,8 @@ interrupts = <5 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart0>; status = "disabled"; }; @@ -164,6 +311,8 @@ interrupts = <6 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart1>; status = "disabled"; }; @@ -173,6 +322,8 @@ interrupts = <7 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart2>; status = "disabled"; }; @@ -182,6 +333,8 @@ interrupts = <8 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart3>; status = "disabled"; }; @@ -215,6 +368,8 @@ >; atmel,nand-addr-offset = <21>; atmel,nand-cmd-offset = <22>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_nand>; gpios = <&pioD 5 0 &pioD 4 0 0 diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts index 912b2c283d6f8d34ac7ac8273b8130360547ef81..0376bf4fd66b81860999a46e581f6879ce35592a 100644 --- a/arch/arm/boot/dts/at91sam9n12ek.dts +++ b/arch/arm/boot/dts/at91sam9n12ek.dts @@ -45,6 +45,28 @@ i2c1: i2c@f8014000 { status = "okay"; }; + + mmc0: mmc@f0008000 { + pinctrl-0 = < + &pinctrl_board_mmc0 + &pinctrl_mmc0_slot0_clk_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioA 7 0>; + }; + }; + + pinctrl@fffff400 { + mmc0 { + pinctrl_board_mmc0: mmc0-board { + atmel,pins = + <0 7 0x0 0x5>; /* PA7 gpio CD pin pull up and deglitch */ + }; + }; + }; }; nand0: nand@40000000 { diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/at91sam9x25.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..54eb33ba6d22ba6e308d756518e8481056a19890 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9x25.dtsi @@ -0,0 +1,49 @@ +/* + * at91sam9x25.dtsi - Device Tree Include file for AT91SAM9X25 SoC + * + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2. + */ + +/include/ "at91sam9x5.dtsi" + +/ { + model = "Atmel AT91SAM9X25 SoC"; + compatible = "atmel, at91sam9x25, atmel,at91sam9x5"; + + ahb { + apb { + pinctrl@fffff400 { + atmel,mux-mask = < + /* A B C */ + 0xffffffff 0xffe03fff 0xc000001c /* pioA */ + 0x0007ffff 0x00047e3f 0x00000000 /* pioB */ + 0x80000000 0xfffd0000 0xb83fffff /* pioC */ + 0x003fffff 0x003f8000 0x00000000 /* pioD */ + >; + + macb1 { + pinctrl_macb1_rmii: macb1_rmii-0 { + atmel,pins = + <2 16 0x2 0x0 /* PC16 periph B */ + 2 18 0x2 0x0 /* PC18 periph B */ + 2 19 0x2 0x0 /* PC19 periph B */ + 2 20 0x2 0x0 /* PC20 periph B */ + 2 21 0x2 0x0 /* PC21 periph B */ + 2 27 0x2 0x0 /* PC27 periph B */ + 2 28 0x2 0x0 /* PC28 periph B */ + 2 29 0x2 0x0 /* PC29 periph B */ + 2 30 0x2 0x0 /* PC30 periph B */ + 2 31 0x2 0x0>; /* PC31 periph B */ + }; + }; + }; + + macb1: ethernet@f8030000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb1_rmii>; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/at91sam9x25ek.dts new file mode 100644 index 0000000000000000000000000000000000000000..af907eaa1f2588b44b1da7a2310aee72dc016c17 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9x25ek.dts @@ -0,0 +1,16 @@ +/* + * at91sam9x25ek.dts - Device Tree file for AT91SAM9X25-EK board + * + * Copyright (C) 2012 Atmel, + * 2012 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ +/dts-v1/; +/include/ "at91sam9x25.dtsi" +/include/ "at91sam9x5ek.dtsi" + +/ { + model = "Atmel AT91SAM9G25-EK"; + compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; +}; diff --git a/arch/arm/boot/dts/at91sam9x35.dtsi b/arch/arm/boot/dts/at91sam9x35.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..fb102d6126ce696234133a2869c7f84a5db888ee --- /dev/null +++ b/arch/arm/boot/dts/at91sam9x35.dtsi @@ -0,0 +1,28 @@ +/* + * at91sam9x35.dtsi - Device Tree Include file for AT91SAM9X35 SoC + * + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2. + */ + +/include/ "at91sam9x5.dtsi" + +/ { + model = "Atmel AT91SAM9X35 SoC"; + compatible = "atmel, at91sam9x35, atmel,at91sam9x5"; + + ahb { + apb { + pinctrl@fffff400 { + atmel,mux-mask = < + /* A B C */ + 0xffffffff 0xffe03fff 0xc000000c /* pioA */ + 0x000406ff 0x00047e3f 0x00000000 /* pioB */ + 0xfdffffff 0x00000000 0xb83fffff /* pioC */ + 0x003fffff 0x003f8000 0x00000000 /* pioD */ + >; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/at91sam9x35ek.dts b/arch/arm/boot/dts/at91sam9x35ek.dts new file mode 100644 index 0000000000000000000000000000000000000000..5ccb607b541427d81e5ac637f1669ed58c1b104a --- /dev/null +++ b/arch/arm/boot/dts/at91sam9x35ek.dts @@ -0,0 +1,16 @@ +/* + * at91sam9x35ek.dts - Device Tree file for AT91SAM9X35-EK board + * + * Copyright (C) 2012 Atmel, + * 2012 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ +/dts-v1/; +/include/ "at91sam9x35.dtsi" +/include/ "at91sam9x5ek.dtsi" + +/ { + model = "Atmel AT91SAM9X35-EK"; + compatible = "atmel,at91sam9x35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; +}; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 03fc136421c5e31b01649c9caacdaf134bef4560..7ee49e8daf987af65060b8b058f8b29a6ff2e6d0 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -111,50 +111,244 @@ interrupts = <21 4 0>; }; - pioA: gpio@fffff400 { - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; - reg = <0xfffff400 0x100>; - interrupts = <2 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; - }; + pinctrl@fffff400 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus"; + ranges = <0xfffff400 0xfffff400 0x800>; + + /* shared pinctrl settings */ + dbgu { + pinctrl_dbgu: dbgu-0 { + atmel,pins = + <0 9 0x1 0x0 /* PA9 periph A */ + 0 10 0x1 0x1>; /* PA10 periph A with pullup */ + }; + }; - pioB: gpio@fffff600 { - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; - reg = <0xfffff600 0x100>; - interrupts = <2 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; + usart0 { + pinctrl_usart0: usart0-0 { + atmel,pins = + <0 0 0x1 0x1 /* PA0 periph A with pullup */ + 0 1 0x1 0x0>; /* PA1 periph A */ + }; + + pinctrl_usart0_rts: usart0_rts-0 { + atmel,pins = + <0 2 0x1 0x0>; /* PA2 periph A */ + }; + + pinctrl_usart0_cts: usart0_cts-0 { + atmel,pins = + <0 3 0x1 0x0>; /* PA3 periph A */ + }; + }; + + usart1 { + pinctrl_usart1: usart1-0 { + atmel,pins = + <0 5 0x1 0x1 /* PA5 periph A with pullup */ + 0 6 0x1 0x0>; /* PA6 periph A */ + }; + + pinctrl_usart1_rts: usart1_rts-0 { + atmel,pins = + <3 27 0x3 0x0>; /* PC27 periph C */ + }; + + pinctrl_usart1_cts: usart1_cts-0 { + atmel,pins = + <3 28 0x3 0x0>; /* PC28 periph C */ + }; + }; + + usart2 { + pinctrl_usart2: usart2-0 { + atmel,pins = + <0 7 0x1 0x1 /* PA7 periph A with pullup */ + 0 8 0x1 0x0>; /* PA8 periph A */ + }; + + pinctrl_uart2_rts: uart2_rts-0 { + atmel,pins = + <0 0 0x2 0x0>; /* PB0 periph B */ + }; + + pinctrl_uart2_cts: uart2_cts-0 { + atmel,pins = + <0 1 0x2 0x0>; /* PB1 periph B */ + }; + }; + + usart3 { + pinctrl_uart3: usart3-0 { + atmel,pins = + <3 23 0x2 0x1 /* PC22 periph B with pullup */ + 3 23 0x2 0x0>; /* PC23 periph B */ + }; + + pinctrl_usart3_rts: usart3_rts-0 { + atmel,pins = + <3 24 0x2 0x0>; /* PC24 periph B */ + }; + + pinctrl_usart3_cts: usart3_cts-0 { + atmel,pins = + <3 25 0x2 0x0>; /* PC25 periph B */ + }; + }; + + uart0 { + pinctrl_uart0: uart0-0 { + atmel,pins = + <3 8 0x3 0x0 /* PC8 periph C */ + 3 9 0x3 0x1>; /* PC9 periph C with pullup */ + }; + }; + + uart1 { + pinctrl_uart1: uart1-0 { + atmel,pins = + <3 16 0x3 0x0 /* PC16 periph C */ + 3 17 0x3 0x1>; /* PC17 periph C with pullup */ + }; + }; + + nand { + pinctrl_nand: nand-0 { + atmel,pins = + <3 4 0x0 0x1 /* PD5 gpio RDY pin pull_up */ + 3 5 0x0 0x1>; /* PD4 gpio enable pin pull_up */ + }; + }; + + macb0 { + pinctrl_macb0_rmii: macb0_rmii-0 { + atmel,pins = + <1 0 0x1 0x0 /* PB0 periph A */ + 1 1 0x1 0x0 /* PB1 periph A */ + 1 2 0x1 0x0 /* PB2 periph A */ + 1 3 0x1 0x0 /* PB3 periph A */ + 1 4 0x1 0x0 /* PB4 periph A */ + 1 5 0x1 0x0 /* PB5 periph A */ + 1 6 0x1 0x0 /* PB6 periph A */ + 1 7 0x1 0x0 /* PB7 periph A */ + 1 9 0x1 0x0 /* PB9 periph A */ + 1 10 0x1 0x0>; /* PB10 periph A */ + }; + + pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 { + atmel,pins = + <1 8 0x1 0x0 /* PA8 periph A */ + 1 11 0x1 0x0 /* PA11 periph A */ + 1 12 0x1 0x0 /* PA12 periph A */ + 1 13 0x1 0x0 /* PA13 periph A */ + 1 14 0x1 0x0 /* PA14 periph A */ + 1 15 0x1 0x0 /* PA15 periph A */ + 1 16 0x1 0x0 /* PA16 periph A */ + 1 17 0x1 0x0>; /* PA17 periph A */ + }; + }; + + mmc0 { + pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 { + atmel,pins = + <0 17 0x1 0x0 /* PA17 periph A */ + 0 16 0x1 0x1 /* PA16 periph A with pullup */ + 0 15 0x1 0x1>; /* PA15 periph A with pullup */ + }; + + pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 { + atmel,pins = + <0 18 0x1 0x1 /* PA18 periph A with pullup */ + 0 19 0x1 0x1 /* PA19 periph A with pullup */ + 0 20 0x1 0x1>; /* PA20 periph A with pullup */ + }; + }; + + mmc1 { + pinctrl_mmc1_slot0_clk_cmd_dat0: mmc1_slot0_clk_cmd_dat0-0 { + atmel,pins = + <0 13 0x2 0x0 /* PA13 periph B */ + 0 12 0x2 0x1 /* PA12 periph B with pullup */ + 0 11 0x2 0x1>; /* PA11 periph B with pullup */ + }; + + pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 { + atmel,pins = + <0 2 0x2 0x1 /* PA2 periph B with pullup */ + 0 3 0x2 0x1 /* PA3 periph B with pullup */ + 0 4 0x2 0x1>; /* PA4 periph B with pullup */ + }; + }; + + pioA: gpio@fffff400 { + compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + reg = <0xfffff400 0x200>; + interrupts = <2 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioB: gpio@fffff600 { + compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + reg = <0xfffff600 0x200>; + interrupts = <2 4 1>; + #gpio-cells = <2>; + gpio-controller; + #gpio-lines = <19>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioC: gpio@fffff800 { + compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + reg = <0xfffff800 0x200>; + interrupts = <3 4 1>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + pioD: gpio@fffffa00 { + compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + reg = <0xfffffa00 0x200>; + interrupts = <3 4 1>; + #gpio-cells = <2>; + gpio-controller; + #gpio-lines = <22>; + interrupt-controller; + #interrupt-cells = <2>; + }; }; - pioC: gpio@fffff800 { - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; - reg = <0xfffff800 0x100>; - interrupts = <3 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; + mmc0: mmc@f0008000 { + compatible = "atmel,hsmci"; + reg = <0xf0008000 0x600>; + interrupts = <12 4 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; }; - pioD: gpio@fffffa00 { - compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; - reg = <0xfffffa00 0x100>; - interrupts = <3 4 1>; - #gpio-cells = <2>; - gpio-controller; - interrupt-controller; - #interrupt-cells = <2>; + mmc1: mmc@f000c000 { + compatible = "atmel,hsmci"; + reg = <0xf000c000 0x600>; + interrupts = <26 4 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; }; dbgu: serial@fffff200 { compatible = "atmel,at91sam9260-usart"; reg = <0xfffff200 0x200>; interrupts = <1 4 7>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dbgu>; status = "disabled"; }; @@ -164,6 +358,8 @@ interrupts = <5 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart0>; status = "disabled"; }; @@ -173,6 +369,8 @@ interrupts = <6 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart1>; status = "disabled"; }; @@ -182,6 +380,8 @@ interrupts = <7 4 5>; atmel,use-dma-rx; atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usart2>; status = "disabled"; }; @@ -189,6 +389,8 @@ compatible = "cdns,at32ap7000-macb", "cdns,macb"; reg = <0xf802c000 0x100>; interrupts = <24 4 3>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb0_rmii>; status = "disabled"; }; @@ -273,6 +475,8 @@ >; atmel,nand-addr-offset = <21>; atmel,nand-cmd-offset = <22>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_nand>; gpios = <&pioD 5 0 &pioD 4 0 0 diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..8a7cf1d9cf5db6f71ee002725151a6d968da40fa --- /dev/null +++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi @@ -0,0 +1,101 @@ +/* + * at91sam9x5ek.dtsi - Device Tree file for AT91SAM9x5CM Base board + * + * Copyright (C) 2012 Atmel, + * 2012 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ +/include/ "at91sam9x5cm.dtsi" + +/ { + model = "Atmel AT91SAM9X5-EK"; + compatible = "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; + + chosen { + bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"; + }; + + ahb { + apb { + mmc0: mmc@f0008000 { + pinctrl-0 = < + &pinctrl_board_mmc0 + &pinctrl_mmc0_slot0_clk_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 15 0>; + }; + }; + + mmc1: mmc@f000c000 { + pinctrl-0 = < + &pinctrl_board_mmc1 + &pinctrl_mmc1_slot0_clk_cmd_dat0 + &pinctrl_mmc1_slot0_dat1_3>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 14 0>; + }; + }; + + dbgu: serial@fffff200 { + status = "okay"; + }; + + usart0: serial@f801c000 { + status = "okay"; + }; + + macb0: ethernet@f802c000 { + phy-mode = "rmii"; + status = "okay"; + }; + + i2c0: i2c@f8010000 { + status = "okay"; + }; + + i2c1: i2c@f8014000 { + status = "okay"; + }; + + i2c2: i2c@f8018000 { + status = "okay"; + }; + + pinctrl@fffff400 { + mmc0 { + pinctrl_board_mmc0: mmc0-board { + atmel,pins = + <3 15 0x0 0x5>; /* PD15 gpio CD pin pull up and deglitch */ + }; + }; + + mmc1 { + pinctrl_board_mmc1: mmc1-board { + atmel,pins = + <3 14 0x0 0x5>; /* PD14 gpio CD pin pull up and deglitch */ + }; + }; + }; + }; + + usb0: ohci@00600000 { + status = "okay"; + num-ports = <2>; + atmel,vbus-gpio = <&pioD 19 1 + &pioD 20 1 + >; + }; + + usb1: ehci@00700000 { + status = "okay"; + }; + }; +}; diff --git a/arch/arm/boot/dts/pm9g45.dts b/arch/arm/boot/dts/pm9g45.dts new file mode 100644 index 0000000000000000000000000000000000000000..387fedb58988bf4f54038f6a2466cd9290569e6d --- /dev/null +++ b/arch/arm/boot/dts/pm9g45.dts @@ -0,0 +1,165 @@ +/* + * pm9g45.dts - Device Tree file for Ronetix pm9g45 board + * + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2. + */ +/dts-v1/; +/include/ "at91sam9g45.dtsi" + +/ { + model = "Ronetix pm9g45"; + compatible = "ronetix,pm9g45", "atmel,at91sam9g45", "atmel,at91sam9"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory { + reg = <0x70000000 0x8000000>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + main_clock: clock@0 { + compatible = "atmel,osc", "fixed-clock"; + clock-frequency = <12000000>; + }; + }; + + ahb { + apb { + dbgu: serial@ffffee00 { + status = "okay"; + }; + + pinctrl@fffff200 { + + board { + pinctrl_board_nand: nand0-board { + atmel,pins = + <3 3 0x0 0x1 /* PD3 gpio RDY pin pull_up*/ + 2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */ + }; + }; + + mmc { + pinctrl_board_mmc: mmc0-board { + atmel,pins = + <3 6 0x0 0x5>; /* PD6 gpio CD pin pull_up and deglitch */ + }; + }; + }; + + mmc0: mmc@fff80000 { + pinctrl-0 = < + &pinctrl_board_mmc + &pinctrl_mmc0_slot0_clk_cmd_dat0 + &pinctrl_mmc0_slot0_dat1_3>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 6 0>; + }; + }; + + macb0: ethernet@fffbc000 { + phy-mode = "rmii"; + status = "okay"; + }; + + }; + + nand0: nand@40000000 { + nand-bus-width = <8>; + nand-ecc-mode = "soft"; + nand-on-flash-bbt; + pinctrl-0 = <&pinctrl_board_nand>; + + gpios = <&pioD 3 0 + &pioC 14 0 + 0 + >; + + status = "okay"; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x0 0x20000>; + }; + + barebox@20000 { + label = "barebox"; + reg = <0x20000 0x40000>; + }; + + bareboxenv@60000 { + label = "bareboxenv"; + reg = <0x60000 0x1A0000>; + }; + + kernel@200000 { + label = "bareboxenv2"; + reg = <0x200000 0x300000>; + }; + + kernel@500000 { + label = "root"; + reg = <0x500000 0x400000>; + }; + + data@900000 { + label = "data"; + reg = <0x900000 0x8340000>; + }; + }; + + usb0: ohci@00700000 { + status = "okay"; + num-ports = <2>; + }; + + usb1: ehci@00800000 { + status = "okay"; + }; + }; + + leds { + compatible = "gpio-leds"; + + led0 { + label = "led0"; + gpios = <&pioD 0 1>; + linux,default-trigger = "nand-disk"; + }; + + led1 { + label = "led1"; + gpios = <&pioD 31 0>; + linux,default-trigger = "heartbeat"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + + right { + label = "SW4"; + gpios = <&pioE 7 1>; + linux,code = <106>; + }; + + up { + label = "SW3"; + gpios = <&pioE 8 1>; + linux,code = <103>; + }; + }; +}; diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts index dd4358bc26e228bd78a1eb35bea71ed1b177a0cf..2e4c5727468e1c4362c911f44dd44c44d0431524 100644 --- a/arch/arm/boot/dts/spear1310-evb.dts +++ b/arch/arm/boot/dts/spear1310-evb.dts @@ -181,6 +181,10 @@ status = "okay"; }; + gpio@d8400000 { + status = "okay"; + }; + i2c0: i2c@e0280000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi index 419ea7413d232b510bdd532064029520ec4336a5..7cd25eb4f8e00a14c317fbbc46854bd7641bdeb9 100644 --- a/arch/arm/boot/dts/spear1310.dtsi +++ b/arch/arm/boot/dts/spear1310.dtsi @@ -70,6 +70,12 @@ status = "disabled"; }; + pinmux: pinmux@e0700000 { + compatible = "st,spear1310-pinmux"; + reg = <0xe0700000 0x1000>; + #gpio-range-cells = <2>; + }; + spi1: spi@5d400000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x5d400000 0x1000>; @@ -179,6 +185,27 @@ thermal@e07008c4 { st,thermal-flags = <0x7000>; }; + + gpiopinctrl: gpio@d8400000 { + compatible = "st,spear-plgpio"; + reg = <0xd8400000 0x1000>; + interrupts = <0 100 0x4>; + #interrupt-cells = <1>; + interrupt-controller; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinmux 0 246>; + status = "disabled"; + + st-plgpio,ngpio = <246>; + st-plgpio,enb-reg = <0xd0>; + st-plgpio,wdata-reg = <0x90>; + st-plgpio,dir-reg = <0xb0>; + st-plgpio,ie-reg = <0x30>; + st-plgpio,rdata-reg = <0x70>; + st-plgpio,mis-reg = <0x10>; + st-plgpio,eit-reg = <0x50>; + }; }; }; }; diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts index c9a54e06fb6849314d3c4bc25031f7153608d775..045f7123ffac5a26eb42e4e025ec88015164075a 100644 --- a/arch/arm/boot/dts/spear1340-evb.dts +++ b/arch/arm/boot/dts/spear1340-evb.dts @@ -193,6 +193,10 @@ status = "okay"; }; + gpio@e2800000 { + status = "okay"; + }; + i2c0: i2c@e0280000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi index d71fe2a68f098460249e076d54326d7f58fbd665..6c09eb0a1b2bbad90683f7311c14f052a2e21ac7 100644 --- a/arch/arm/boot/dts/spear1340.dtsi +++ b/arch/arm/boot/dts/spear1340.dtsi @@ -24,6 +24,12 @@ status = "disabled"; }; + pinmux: pinmux@e0700000 { + compatible = "st,spear1340-pinmux"; + reg = <0xe0700000 0x1000>; + #gpio-range-cells = <2>; + }; + spi1: spi@5d400000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x5d400000 0x1000>; @@ -51,6 +57,26 @@ thermal@e07008c4 { st,thermal-flags = <0x2a00>; }; + + gpiopinctrl: gpio@e2800000 { + compatible = "st,spear-plgpio"; + reg = <0xe2800000 0x1000>; + interrupts = <0 107 0x4>; + #interrupt-cells = <1>; + interrupt-controller; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinmux 0 252>; + status = "disabled"; + + st-plgpio,ngpio = <250>; + st-plgpio,wdata-reg = <0x40>; + st-plgpio,dir-reg = <0x00>; + st-plgpio,ie-reg = <0x80>; + st-plgpio,rdata-reg = <0x20>; + st-plgpio,mis-reg = <0xa0>; + st-plgpio,eit-reg = <0x60>; + }; }; }; }; diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi index 62fc4fb3e5f92f079cd3caaf0ccdf852e1ff01d1..930303e48df932e42f1c9d4042cbe5290fff4d20 100644 --- a/arch/arm/boot/dts/spear310.dtsi +++ b/arch/arm/boot/dts/spear310.dtsi @@ -22,9 +22,10 @@ 0xb0000000 0xb0000000 0x10000000 0xd0000000 0xd0000000 0x30000000>; - pinmux@b4000000 { + pinmux: pinmux@b4000000 { compatible = "st,spear310-pinmux"; reg = <0xb4000000 0x1000>; + #gpio-range-cells = <2>; }; fsmc: flash@44000000 { @@ -75,6 +76,25 @@ reg = <0xb2200000 0x1000>; status = "disabled"; }; + + gpiopinctrl: gpio@b4000000 { + compatible = "st,spear-plgpio"; + reg = <0xb4000000 0x1000>; + #interrupt-cells = <1>; + interrupt-controller; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinmux 0 102>; + status = "disabled"; + + st-plgpio,ngpio = <102>; + st-plgpio,enb-reg = <0x10>; + st-plgpio,wdata-reg = <0x20>; + st-plgpio,dir-reg = <0x30>; + st-plgpio,ie-reg = <0x50>; + st-plgpio,rdata-reg = <0x40>; + st-plgpio,mis-reg = <0x60>; + }; }; }; }; diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts index 082328bd64abd1e09591b1555b7b130c35dd06a6..ad4bfc68ee059b4632cde6b69f9a851a064cf90e 100644 --- a/arch/arm/boot/dts/spear320-evb.dts +++ b/arch/arm/boot/dts/spear320-evb.dts @@ -164,6 +164,10 @@ status = "okay"; }; + gpio@b3000000 { + status = "okay"; + }; + i2c0: i2c@d0180000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi index 1f49d69595a06996b0c8b48d631ed116716f7abb..67d7ada7127556eb5b5264ae171145744f82b36d 100644 --- a/arch/arm/boot/dts/spear320.dtsi +++ b/arch/arm/boot/dts/spear320.dtsi @@ -21,9 +21,10 @@ ranges = <0x40000000 0x40000000 0x80000000 0xd0000000 0xd0000000 0x30000000>; - pinmux@b3000000 { + pinmux: pinmux@b3000000 { compatible = "st,spear320-pinmux"; reg = <0xb3000000 0x1000>; + #gpio-range-cells = <2>; }; clcd@90000000 { @@ -90,6 +91,26 @@ reg = <0xa4000000 0x1000>; status = "disabled"; }; + + gpiopinctrl: gpio@b3000000 { + compatible = "st,spear-plgpio"; + reg = <0xb3000000 0x1000>; + #interrupt-cells = <1>; + interrupt-controller; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinmux 0 102>; + status = "disabled"; + + st-plgpio,ngpio = <102>; + st-plgpio,enb-reg = <0x24>; + st-plgpio,wdata-reg = <0x34>; + st-plgpio,dir-reg = <0x44>; + st-plgpio,ie-reg = <0x64>; + st-plgpio,rdata-reg = <0x54>; + st-plgpio,mis-reg = <0x84>; + st-plgpio,eit-reg = <0x94>; + }; }; }; }; diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index 67bc571ed0c37c331a179703866ba861b1cdd2c1..b175577d7abb5aec9541461e35407f0f9059c04a 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig @@ -111,6 +111,7 @@ CONFIG_I2C=y CONFIG_I2C_GPIO=y CONFIG_SPI=y CONFIG_SPI_ATMEL=y +CONFIG_PINCTRL_AT91=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_AT91SAM9X_WATCHDOG=y diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 043624219b55a25ebdc50c86a7399dda604392a3..e34c1bdb804db921ecf92528b8721131d54c1449 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -494,8 +494,17 @@ endif comment "Generic Board Type" +config MACH_AT91RM9200_DT + bool "Atmel AT91RM9200 Evaluation Kits with device-tree support" + depends on SOC_AT91RM9200 + select USE_OF + help + Select this if you want to experiment device-tree with + an Atmel RM9200 Evaluation Kit. + config MACH_AT91SAM_DT bool "Atmel AT91SAM Evaluation Kits with device-tree support" + depends on SOC_AT91SAM9 select USE_OF help Select this if you want to experiment device-tree with diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 3bb7a51efc9d92ee8e1eed574b4b925d5a7485e1..b38a1dcb79b82759c1aad5dc6d52a70527d0a6b2 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o # AT91SAM board with device-tree +obj-$(CONFIG_MACH_AT91RM9200_DT) += board-rm9200-dt.o obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o # AT91X40 board-specific support diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index 5269825194a8a41c620ffa3da9f5a2cf5269bcb5..6cceb42a4c33814390e4be6d5f591e3a5cbba662 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -194,6 +194,24 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_ID("pioB", &pioB_clk), CLKDEV_CON_ID("pioC", &pioC_clk), CLKDEV_CON_ID("pioD", &pioD_clk), + /* usart lookup table for DT entries */ + CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck), + CLKDEV_CON_DEV_ID("usart", "fffc0000.serial", &usart0_clk), + CLKDEV_CON_DEV_ID("usart", "fffc4000.serial", &usart1_clk), + CLKDEV_CON_DEV_ID("usart", "fffc8000.serial", &usart2_clk), + CLKDEV_CON_DEV_ID("usart", "fffcc000.serial", &usart3_clk), + /* tc lookup table for DT entries */ + CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk), + CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk), + CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk), + CLKDEV_CON_DEV_ID("t0_clk", "fffa4000.timer", &tc3_clk), + CLKDEV_CON_DEV_ID("t1_clk", "fffa4000.timer", &tc4_clk), + CLKDEV_CON_DEV_ID("t2_clk", "fffa4000.timer", &tc5_clk), + CLKDEV_CON_DEV_ID("hclk", "300000.ohci", &ohci_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk), + CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioD_clk), }; static struct clk_lookup usart_clocks_lookups[] = { @@ -361,10 +379,10 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = { 0 /* Advanced Interrupt Controller (IRQ6) */ }; -struct at91_init_soc __initdata at91rm9200_soc = { +AT91_SOC_START(rm9200) .map_io = at91rm9200_map_io, .default_irq_priority = at91rm9200_default_irq_priority, .ioremap_registers = at91rm9200_ioremap_registers, .register_clocks = at91rm9200_register_clocks, .init = at91rm9200_initialize, -}; +AT91_SOC_END diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index aaa443b48c91f121e2f698792fb94bb4d6e2afa6..cafe98836c8a7979703874a729ce22d6ae3eec86 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include @@ -91,7 +94,8 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id) static struct irqaction at91rm9200_timer_irq = { .name = "at91_tick", .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = at91rm9200_timer_interrupt + .handler = at91rm9200_timer_interrupt, + .irq = NR_IRQS_LEGACY + AT91_ID_SYS, }; static cycle_t read_clk32k(struct clocksource *cs) @@ -179,8 +183,60 @@ static struct clock_event_device clkevt = { void __iomem *at91_st_base; EXPORT_SYMBOL_GPL(at91_st_base); +#ifdef CONFIG_OF +static struct of_device_id at91rm9200_st_timer_ids[] = { + { .compatible = "atmel,at91rm9200-st" }, + { /* sentinel */ } +}; + +static int __init of_at91rm9200_st_init(void) +{ + struct device_node *np; + int ret; + + np = of_find_matching_node(NULL, at91rm9200_st_timer_ids); + if (!np) + goto err; + + at91_st_base = of_iomap(np, 0); + if (!at91_st_base) + goto node_err; + + /* Get the interrupts property */ + ret = irq_of_parse_and_map(np, 0); + if (!ret) + goto ioremap_err; + at91rm9200_timer_irq.irq = ret; + + of_node_put(np); + + return 0; + +ioremap_err: + iounmap(at91_st_base); +node_err: + of_node_put(np); +err: + return -EINVAL; +} +#else +static int __init of_at91rm9200_st_init(void) +{ + return -EINVAL; +} +#endif + void __init at91rm9200_ioremap_st(u32 addr) { +#ifdef CONFIG_OF + struct device_node *np; + + np = of_find_matching_node(NULL, at91rm9200_st_timer_ids); + if (np) { + of_node_put(np); + return; + } +#endif at91_st_base = ioremap(addr, 256); if (!at91_st_base) panic("Impossible to ioremap ST\n"); @@ -191,13 +247,16 @@ void __init at91rm9200_ioremap_st(u32 addr) */ void __init at91rm9200_timer_init(void) { + /* For device tree enabled device: initialize here */ + of_at91rm9200_st_init(); + /* Disable all timer interrupts, and clear any pending ones */ at91_st_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); at91_st_read(AT91_ST_SR); /* Make IRQs happen for the system timer */ - setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq); + setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq); /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used * directly for the clocksource and all clockevents, after adjusting diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index f8202615f4a867f32ffe970cde12f0b6887d2375..c9e029e44d8a8f727805a4cb6dc7e604240cb7e7 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -230,11 +230,15 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk), CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk), CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk), + CLKDEV_CON_DEV_ID("mci_clk", "fffa8000.mmc", &mmc_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), CLKDEV_CON_ID("pioA", &pioA_clk), CLKDEV_CON_ID("pioB", &pioB_clk), CLKDEV_CON_ID("pioC", &pioC_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk), }; static struct clk_lookup usart_clocks_lookups[] = { @@ -390,10 +394,10 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = { 0, /* Advanced Interrupt Controller */ }; -struct at91_init_soc __initdata at91sam9260_soc = { +AT91_SOC_START(sam9260) .map_io = at91sam9260_map_io, .default_irq_priority = at91sam9260_default_irq_priority, .ioremap_registers = at91sam9260_ioremap_registers, .register_clocks = at91sam9260_register_clocks, .init = at91sam9260_initialize, -}; +AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 04295c04b3e03cb99d31aa2f226908ab2a975ec4..4d262f346fd9db22080e418ccb58872dd83e857c 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -334,10 +334,10 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = { 0, /* Advanced Interrupt Controller */ }; -struct at91_init_soc __initdata at91sam9261_soc = { +AT91_SOC_START(sam9261) .map_io = at91sam9261_map_io, .default_irq_priority = at91sam9261_default_irq_priority, .ioremap_registers = at91sam9261_ioremap_registers, .register_clocks = at91sam9261_register_clocks, .init = at91sam9261_initialize, -}; +AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index d6f9c23927c48c92202776d049a582af01b8f520..ed390f6fa2321ae939aff23a221c96f624c7beee 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -211,7 +211,14 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk), CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk), CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk), + CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk), + CLKDEV_CON_DEV_ID("mci_clk", "fff84000.mmc", &mmc1_clk), CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioCDE_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCDE_clk), + CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCDE_clk), }; static struct clk_lookup usart_clocks_lookups[] = { @@ -365,10 +372,10 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = { 0, /* Advanced Interrupt Controller (IRQ1) */ }; -struct at91_init_soc __initdata at91sam9263_soc = { +AT91_SOC_START(sam9263) .map_io = at91sam9263_map_io, .default_irq_priority = at91sam9263_default_irq_priority, .ioremap_registers = at91sam9263_ioremap_registers, .register_clocks = at91sam9263_register_clocks, .init = at91sam9263_initialize, -}; +AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 84af1b506d92a0b1e9e88c885b1d57be95fbf40b..c5c2acc4bf221ab62a3a8cb79c3618488016eff1 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -256,10 +256,18 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk), CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk), CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk), + CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk), + CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk), CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk), CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioC_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioDE_clk), + CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioDE_clk), + CLKDEV_CON_ID("pioA", &pioA_clk), CLKDEV_CON_ID("pioB", &pioB_clk), CLKDEV_CON_ID("pioC", &pioC_clk), @@ -409,10 +417,10 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = { 0, /* Advanced Interrupt Controller (IRQ0) */ }; -struct at91_init_soc __initdata at91sam9g45_soc = { +AT91_SOC_START(sam9g45) .map_io = at91sam9g45_map_io, .default_irq_priority = at91sam9g45_default_irq_priority, .ioremap_registers = at91sam9g45_ioremap_registers, .register_clocks = at91sam9g45_register_clocks, .init = at91sam9g45_initialize, -}; +AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c index 732d3d3f4ec5f7f93430839330d0e473a8063c20..70b3a99244abbc131cb6874c6fa8ed770ae733c7 100644 --- a/arch/arm/mach-at91/at91sam9n12.c +++ b/arch/arm/mach-at91/at91sam9n12.c @@ -168,13 +168,14 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk), CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk), CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk), + CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc_clk), CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk), CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk), CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk), - CLKDEV_CON_ID("pioA", &pioAB_clk), - CLKDEV_CON_ID("pioB", &pioAB_clk), - CLKDEV_CON_ID("pioC", &pioCD_clk), - CLKDEV_CON_ID("pioD", &pioCD_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk), + CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk), /* additional fake clock for macb_hclk */ CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk), CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk), @@ -223,13 +224,10 @@ static void __init at91sam9n12_map_io(void) void __init at91sam9n12_initialize(void) { at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0); - - /* Register GPIO subsystem (using DT) */ - at91_gpio_init(NULL, 0); } -struct at91_init_soc __initdata at91sam9n12_soc = { +AT91_SOC_START(sam9n12) .map_io = at91sam9n12_map_io, .register_clocks = at91sam9n12_register_clocks, .init = at91sam9n12_initialize, -}; +AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index 72e908412222615134fc0530cc339348093f76be..cbe72e44c13fff62dc537ce8db955408c0284ab1 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -338,10 +338,10 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = { 0, /* Advanced Interrupt Controller */ }; -struct at91_init_soc __initdata at91sam9rl_soc = { +AT91_SOC_START(sam9rl) .map_io = at91sam9rl_map_io, .default_irq_priority = at91sam9rl_default_irq_priority, .ioremap_registers = at91sam9rl_ioremap_registers, .register_clocks = at91sam9rl_register_clocks, .init = at91sam9rl_initialize, -}; +AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index e5035380dcbce16e806fb460625fd73d9a3c1153..3c729f0e2d3c8abfe8ed920cb4778a5cee2d4214 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -229,15 +229,17 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk), CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk), CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk), + CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk), + CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk), CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk), CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk), CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk), CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk), CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk), - CLKDEV_CON_ID("pioA", &pioAB_clk), - CLKDEV_CON_ID("pioB", &pioAB_clk), - CLKDEV_CON_ID("pioC", &pioCD_clk), - CLKDEV_CON_ID("pioD", &pioCD_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk), + CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk), + CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk), /* additional fake clock for macb_hclk */ CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb0_clk), CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk), @@ -313,18 +315,11 @@ static void __init at91sam9x5_map_io(void) at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE); } -void __init at91sam9x5_initialize(void) -{ - /* Register GPIO subsystem (using DT) */ - at91_gpio_init(NULL, 0); -} - /* -------------------------------------------------------------------- * Interrupt initialization * -------------------------------------------------------------------- */ -struct at91_init_soc __initdata at91sam9x5_soc = { +AT91_SOC_START(sam9x5) .map_io = at91sam9x5_map_io, .register_clocks = at91sam9x5_register_clocks, - .init = at91sam9x5_initialize, -}; +AT91_SOC_END diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index e8f45c4e0ea8f01affd71c486d50ea1f42228e4c..3b6a94820fa08d506478de1300cf02858c24dd3e 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c @@ -30,8 +30,6 @@ static const struct of_device_id irq_of_match[] __initconst = { { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, - { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup }, - { .compatible = "atmel,at91sam9x5-gpio", .data = at91_gpio_of_irq_setup }, { /*sentinel*/ } }; diff --git a/arch/arm/mach-at91/board-rm9200-dt.c b/arch/arm/mach-at91/board-rm9200-dt.c new file mode 100644 index 0000000000000000000000000000000000000000..5f9ce3da3fde4f0a75cb3bd18059c31494283891 --- /dev/null +++ b/arch/arm/mach-at91/board-rm9200-dt.c @@ -0,0 +1,57 @@ +/* + * Setup code for AT91RM9200 Evaluation Kits with Device Tree support + * + * Copyright (C) 2011 Atmel, + * 2011 Nicolas Ferre + * 2012 Joachim Eastwood + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "at91_aic.h" +#include "generic.h" + + +static const struct of_device_id irq_of_match[] __initconst = { + { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, + { /*sentinel*/ } +}; + +static void __init at91rm9200_dt_init_irq(void) +{ + of_irq_init(irq_of_match); +} + +static void __init at91rm9200_dt_device_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static const char *at91rm9200_dt_board_compat[] __initdata = { + "atmel,at91rm9200", + NULL +}; + +DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)") + .timer = &at91rm9200_timer, + .map_io = at91_map_io, + .handle_irq = at91_aic_handle_irq, + .init_early = at91rm9200_dt_initialize, + .init_irq = at91rm9200_dt_init_irq, + .init_machine = at91rm9200_dt_device_init, + .dt_compat = at91rm9200_dt_board_compat, +MACHINE_END diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index b62f560e6c75fbe838200cb03b3347a8c3a15241..fc593d615e7d3dee678a1a2f67f6fc446c9aa853 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -20,6 +20,7 @@ extern void __init at91_init_sram(int bank, unsigned long base, extern void __init at91rm9200_set_type(int type); extern void __init at91_initialize(unsigned long main_clock); extern void __init at91x40_initialize(unsigned long main_clock); +extern void __init at91rm9200_dt_initialize(void); extern void __init at91_dt_initialize(void); /* Interrupts */ diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index be42cf0e74bddd39ded6e1b54d7f17d351a24bc1..c5d7e1e9d7578cffc8265e9205c2a8e8162a311a 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c @@ -23,8 +23,6 @@ #include #include #include -#include -#include #include @@ -33,6 +31,8 @@ #include "generic.h" +#define MAX_NB_GPIO_PER_BANK 32 + struct at91_gpio_chip { struct gpio_chip chip; struct at91_gpio_chip *next; /* Bank sharing same clock */ @@ -46,6 +46,7 @@ struct at91_gpio_chip { #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip) +static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset); static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip); static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val); static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset); @@ -55,26 +56,27 @@ static int at91_gpiolib_direction_input(struct gpio_chip *chip, unsigned offset); static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset); -#define AT91_GPIO_CHIP(name, nr_gpio) \ +#define AT91_GPIO_CHIP(name) \ { \ .chip = { \ .label = name, \ + .request = at91_gpiolib_request, \ .direction_input = at91_gpiolib_direction_input, \ .direction_output = at91_gpiolib_direction_output, \ .get = at91_gpiolib_get, \ .set = at91_gpiolib_set, \ .dbg_show = at91_gpiolib_dbg_show, \ .to_irq = at91_gpiolib_to_irq, \ - .ngpio = nr_gpio, \ + .ngpio = MAX_NB_GPIO_PER_BANK, \ }, \ } static struct at91_gpio_chip gpio_chip[] = { - AT91_GPIO_CHIP("pioA", 32), - AT91_GPIO_CHIP("pioB", 32), - AT91_GPIO_CHIP("pioC", 32), - AT91_GPIO_CHIP("pioD", 32), - AT91_GPIO_CHIP("pioE", 32), + AT91_GPIO_CHIP("pioA"), + AT91_GPIO_CHIP("pioB"), + AT91_GPIO_CHIP("pioC"), + AT91_GPIO_CHIP("pioD"), + AT91_GPIO_CHIP("pioE"), }; static int gpio_banks; @@ -89,7 +91,7 @@ static unsigned long at91_gpio_caps; static inline void __iomem *pin_to_controller(unsigned pin) { - pin /= 32; + pin /= MAX_NB_GPIO_PER_BANK; if (likely(pin < gpio_banks)) return gpio_chip[pin].regbase; @@ -98,7 +100,7 @@ static inline void __iomem *pin_to_controller(unsigned pin) static inline unsigned pin_to_mask(unsigned pin) { - return 1 << (pin % 32); + return 1 << (pin % MAX_NB_GPIO_PER_BANK); } @@ -713,80 +715,6 @@ postcore_initcall(at91_gpio_debugfs_init); */ static struct lock_class_key gpio_lock_class; -#if defined(CONFIG_OF) -static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - struct at91_gpio_chip *at91_gpio = h->host_data; - - irq_set_lockdep_class(virq, &gpio_lock_class); - - /* - * Can use the "simple" and not "edge" handler since it's - * shorter, and the AIC handles interrupts sanely. - */ - irq_set_chip_and_handler(virq, &gpio_irqchip, - handle_simple_irq); - set_irq_flags(virq, IRQF_VALID); - irq_set_chip_data(virq, at91_gpio); - - return 0; -} - -static struct irq_domain_ops at91_gpio_ops = { - .map = at91_gpio_irq_map, - .xlate = irq_domain_xlate_twocell, -}; - -int __init at91_gpio_of_irq_setup(struct device_node *node, - struct device_node *parent) -{ - struct at91_gpio_chip *prev = NULL; - int alias_idx = of_alias_get_id(node, "gpio"); - struct at91_gpio_chip *at91_gpio = &gpio_chip[alias_idx]; - - /* Setup proper .irq_set_type function */ - if (has_pio3()) - gpio_irqchip.irq_set_type = alt_gpio_irq_type; - else - gpio_irqchip.irq_set_type = gpio_irq_type; - - /* Disable irqs of this PIO controller */ - __raw_writel(~0, at91_gpio->regbase + PIO_IDR); - - /* Setup irq domain */ - at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio, - &at91_gpio_ops, at91_gpio); - if (!at91_gpio->domain) - panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n", - at91_gpio->pioc_idx); - - /* Setup chained handler */ - if (at91_gpio->pioc_idx) - prev = &gpio_chip[at91_gpio->pioc_idx - 1]; - - /* The toplevel handler handles one bank of GPIOs, except - * on some SoC it can handles up to three... - * We only set up the handler for the first of the list. - */ - if (prev && prev->next == at91_gpio) - return 0; - - at91_gpio->pioc_virq = irq_create_mapping(irq_find_host(parent), - at91_gpio->pioc_hwirq); - irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio); - irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler); - - return 0; -} -#else -int __init at91_gpio_of_irq_setup(struct device_node *node, - struct device_node *parent) -{ - return -EINVAL; -} -#endif - /* * irqdomain initialization: pile up irqdomains on top of AIC range */ @@ -862,6 +790,16 @@ void __init at91_gpio_irq_setup(void) } /* gpiolib support */ +static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset) +{ + struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << offset; + + __raw_writel(mask, pio + PIO_PER); + return 0; +} + static int at91_gpiolib_direction_input(struct gpio_chip *chip, unsigned offset) { @@ -975,81 +913,11 @@ static int __init at91_gpio_setup_clk(int idx) return -EINVAL; } -#ifdef CONFIG_OF_GPIO -static void __init of_at91_gpio_init_one(struct device_node *np) -{ - int alias_idx; - struct at91_gpio_chip *at91_gpio; - - if (!np) - return; - - alias_idx = of_alias_get_id(np, "gpio"); - if (alias_idx >= MAX_GPIO_BANKS) { - pr_err("at91_gpio, failed alias idx(%d) > MAX_GPIO_BANKS(%d), ignoring.\n", - alias_idx, MAX_GPIO_BANKS); - return; - } - - at91_gpio = &gpio_chip[alias_idx]; - at91_gpio->chip.base = alias_idx * at91_gpio->chip.ngpio; - - at91_gpio->regbase = of_iomap(np, 0); - if (!at91_gpio->regbase) { - pr_err("at91_gpio.%d, failed to map registers, ignoring.\n", - alias_idx); - return; - } - - /* Get the interrupts property */ - if (of_property_read_u32(np, "interrupts", &at91_gpio->pioc_hwirq)) { - pr_err("at91_gpio.%d, failed to get interrupts property, ignoring.\n", - alias_idx); - goto ioremap_err; - } - - /* Get capabilities from compatibility property */ - if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio")) - at91_gpio_caps |= AT91_GPIO_CAP_PIO3; - - /* Setup clock */ - if (at91_gpio_setup_clk(alias_idx)) - goto ioremap_err; - - at91_gpio->chip.of_node = np; - gpio_banks = max(gpio_banks, alias_idx + 1); - at91_gpio->pioc_idx = alias_idx; - return; - -ioremap_err: - iounmap(at91_gpio->regbase); -} - -static int __init of_at91_gpio_init(void) -{ - struct device_node *np = NULL; - - /* - * This isn't ideal, but it gets things hooked up until this - * driver is converted into a platform_device - */ - for_each_compatible_node(np, NULL, "atmel,at91rm9200-gpio") - of_at91_gpio_init_one(np); - - return gpio_banks > 0 ? 0 : -EINVAL; -} -#else -static int __init of_at91_gpio_init(void) -{ - return -EINVAL; -} -#endif - static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq) { struct at91_gpio_chip *at91_gpio = &gpio_chip[idx]; - at91_gpio->chip.base = idx * at91_gpio->chip.ngpio; + at91_gpio->chip.base = idx * MAX_NB_GPIO_PER_BANK; at91_gpio->pioc_hwirq = pioc_hwirq; at91_gpio->pioc_idx = idx; @@ -1079,11 +947,11 @@ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks) BUG_ON(nr_banks > MAX_GPIO_BANKS); - if (of_at91_gpio_init() < 0) { - /* No GPIO controller found in device tree */ - for (i = 0; i < nr_banks; i++) - at91_gpio_init_one(i, data[i].regbase, data[i].id); - } + if (of_have_populated_dt()) + return; + + for (i = 0; i < nr_banks; i++) + at91_gpio_init_one(i, data[i].regbase, data[i].id); for (i = 0; i < gpio_banks; i++) { at91_gpio = &gpio_chip[i]; diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 0b32c81730a571484a600577e3037aa5d1573c65..19cdd0b5b39157d895a4c9a3dfdc4a81b10e3495 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -338,6 +339,7 @@ static void at91_dt_rstc(void) } static struct of_device_id ramc_ids[] = { + { .compatible = "atmel,at91rm9200-sdramc" }, { .compatible = "atmel,at91sam9260-sdramc" }, { .compatible = "atmel,at91sam9g45-ddramc" }, { /*sentinel*/ } @@ -436,6 +438,19 @@ static void at91_dt_shdwc(void) of_node_put(np); } +void __init at91rm9200_dt_initialize(void) +{ + at91_dt_ramc(); + + /* Init clock subsystem */ + at91_dt_clock_init(); + + /* Register the processor-specific clocks */ + at91_boot_soc.register_clocks(); + + at91_boot_soc.init(); +} + void __init at91_dt_initialize(void) { at91_dt_rstc(); @@ -448,7 +463,8 @@ void __init at91_dt_initialize(void) /* Register the processor-specific clocks */ at91_boot_soc.register_clocks(); - at91_boot_soc.init(); + if (at91_boot_soc.init) + at91_boot_soc.init(); } #endif @@ -463,4 +479,6 @@ void __init at91_initialize(unsigned long main_clock) at91_boot_soc.register_clocks(); at91_boot_soc.init(); + + pinctrl_provide_dummies(); } diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h index a9cfeb15371959b06d800325b0d9896217842b02..9c6d3d4f9a23ab43d4ba7a1fb58624a0b774b8b4 100644 --- a/arch/arm/mach-at91/soc.h +++ b/arch/arm/mach-at91/soc.h @@ -5,6 +5,7 @@ */ struct at91_init_soc { + int builtin; unsigned int *default_irq_priority; void (*map_io)(void); void (*ioremap_registers)(void); @@ -22,9 +23,18 @@ extern struct at91_init_soc at91sam9rl_soc; extern struct at91_init_soc at91sam9x5_soc; extern struct at91_init_soc at91sam9n12_soc; +#define AT91_SOC_START(_name) \ +struct at91_init_soc __initdata at91##_name##_soc \ + __used \ + = { \ + .builtin = 1, \ + +#define AT91_SOC_END \ +}; + static inline int at91_soc_is_enabled(void) { - return at91_boot_soc.init != NULL; + return at91_boot_soc.builtin; } #if !defined(CONFIG_SOC_AT91RM9200) diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index bfa1eab91f4142cecb3bdd1ce4c4ec1b8e9a9698..22ef8a1abe0835cc7d0143c9456b984794c10113 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,7 @@ #include #include -#include #include -#include #include #include diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index b617eaed0ce58695ac709b460ac29b8ac2d4b1d6..1273931303fb81599201ae0f70c1c71f503b9eda 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -26,8 +26,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c index 6d14454d46094fc4bdd00c66cabff3a0abb800f9..0c2f6628299aa6bc2a7c95b567ff56344dd7df87 100644 --- a/arch/arm/mach-nomadik/i2c-8815nhk.c +++ b/arch/arm/mach-nomadik/i2c-8815nhk.c @@ -4,8 +4,7 @@ #include #include #include -#include -#include +#include /* * There are two busses in the 8815NHK. diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index b8efac4daed89256a8e9dc0257c940af05033fa4..ece8a2dfb8142b9aaec5e8f3b95526be673cb637 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -1445,8 +1445,6 @@ static struct platform_device pinctrl_device = { static struct u300_gpio_platform u300_gpio_plat = { .ports = 7, .gpio_base = 0, - .gpio_irq_base = IRQ_U300_GPIO_BASE, - .pinctrl_device = &pinctrl_device, }; static struct platform_device gpio_device = { @@ -1590,6 +1588,7 @@ static struct platform_device *platform_devs[] __initdata = { &i2c1_device, &keypad_device, &rtc_device, + &pinctrl_device, &gpio_device, &nand_device, &wdog_device, @@ -1804,7 +1803,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board") /* Maintainer: Linus Walleij */ .atag_offset = 0x100, .map_io = u300_map_io, - .nr_irqs = NR_IRQS_U300, + .nr_irqs = 0, .init_irq = u300_init_irq, .handle_irq = vic_handle_irq, .timer = &u300_timer, diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h index e27425a63fa1418837b4becaa23256e0ccbe6706..21d5e76a6cd3da0f123233872c8ebbfa093fb3d5 100644 --- a/arch/arm/mach-u300/include/mach/irqs.h +++ b/arch/arm/mach-u300/include/mach/irqs.h @@ -12,79 +12,69 @@ #ifndef __MACH_IRQS_H #define __MACH_IRQS_H -#define IRQ_U300_INTCON0_START 1 -#define IRQ_U300_INTCON1_START 33 +#define IRQ_U300_INTCON0_START 32 +#define IRQ_U300_INTCON1_START 64 /* These are on INTCON0 - 30 lines */ -#define IRQ_U300_IRQ0_EXT 1 -#define IRQ_U300_IRQ1_EXT 2 -#define IRQ_U300_DMA 3 -#define IRQ_U300_VIDEO_ENC_0 4 -#define IRQ_U300_VIDEO_ENC_1 5 -#define IRQ_U300_AAIF_RX 6 -#define IRQ_U300_AAIF_TX 7 -#define IRQ_U300_AAIF_VGPIO 8 -#define IRQ_U300_AAIF_WAKEUP 9 -#define IRQ_U300_PCM_I2S0_FRAME 10 -#define IRQ_U300_PCM_I2S0_FIFO 11 -#define IRQ_U300_PCM_I2S1_FRAME 12 -#define IRQ_U300_PCM_I2S1_FIFO 13 -#define IRQ_U300_XGAM_GAMCON 14 -#define IRQ_U300_XGAM_CDI 15 -#define IRQ_U300_XGAM_CDICON 16 -#define IRQ_U300_XGAM_PDI 18 -#define IRQ_U300_XGAM_PDICON 19 -#define IRQ_U300_XGAM_GAMEACC 20 -#define IRQ_U300_XGAM_MCIDCT 21 -#define IRQ_U300_APEX 22 -#define IRQ_U300_UART0 23 -#define IRQ_U300_SPI 24 -#define IRQ_U300_TIMER_APP_OS 25 -#define IRQ_U300_TIMER_APP_DD 26 -#define IRQ_U300_TIMER_APP_GP1 27 -#define IRQ_U300_TIMER_APP_GP2 28 -#define IRQ_U300_TIMER_OS 29 -#define IRQ_U300_TIMER_MS 30 -#define IRQ_U300_KEYPAD_KEYBF 31 -#define IRQ_U300_KEYPAD_KEYBR 32 +#define IRQ_U300_IRQ0_EXT 32 +#define IRQ_U300_IRQ1_EXT 33 +#define IRQ_U300_DMA 34 +#define IRQ_U300_VIDEO_ENC_0 35 +#define IRQ_U300_VIDEO_ENC_1 36 +#define IRQ_U300_AAIF_RX 37 +#define IRQ_U300_AAIF_TX 38 +#define IRQ_U300_AAIF_VGPIO 39 +#define IRQ_U300_AAIF_WAKEUP 40 +#define IRQ_U300_PCM_I2S0_FRAME 41 +#define IRQ_U300_PCM_I2S0_FIFO 42 +#define IRQ_U300_PCM_I2S1_FRAME 43 +#define IRQ_U300_PCM_I2S1_FIFO 44 +#define IRQ_U300_XGAM_GAMCON 45 +#define IRQ_U300_XGAM_CDI 46 +#define IRQ_U300_XGAM_CDICON 47 +#define IRQ_U300_XGAM_PDI 49 +#define IRQ_U300_XGAM_PDICON 50 +#define IRQ_U300_XGAM_GAMEACC 51 +#define IRQ_U300_XGAM_MCIDCT 52 +#define IRQ_U300_APEX 53 +#define IRQ_U300_UART0 54 +#define IRQ_U300_SPI 55 +#define IRQ_U300_TIMER_APP_OS 56 +#define IRQ_U300_TIMER_APP_DD 57 +#define IRQ_U300_TIMER_APP_GP1 58 +#define IRQ_U300_TIMER_APP_GP2 59 +#define IRQ_U300_TIMER_OS 60 +#define IRQ_U300_TIMER_MS 61 +#define IRQ_U300_KEYPAD_KEYBF 62 +#define IRQ_U300_KEYPAD_KEYBR 63 /* These are on INTCON1 - 32 lines */ -#define IRQ_U300_GPIO_PORT0 33 -#define IRQ_U300_GPIO_PORT1 34 -#define IRQ_U300_GPIO_PORT2 35 +#define IRQ_U300_GPIO_PORT0 64 +#define IRQ_U300_GPIO_PORT1 65 +#define IRQ_U300_GPIO_PORT2 66 /* These are for DB3150, DB3200 and DB3350 */ -#define IRQ_U300_WDOG 36 -#define IRQ_U300_EVHIST 37 -#define IRQ_U300_MSPRO 38 -#define IRQ_U300_MMCSD_MCIINTR0 39 -#define IRQ_U300_MMCSD_MCIINTR1 40 -#define IRQ_U300_I2C0 41 -#define IRQ_U300_I2C1 42 -#define IRQ_U300_RTC 43 -#define IRQ_U300_NFIF 44 -#define IRQ_U300_NFIF2 45 +#define IRQ_U300_WDOG 67 +#define IRQ_U300_EVHIST 68 +#define IRQ_U300_MSPRO 69 +#define IRQ_U300_MMCSD_MCIINTR0 70 +#define IRQ_U300_MMCSD_MCIINTR1 71 +#define IRQ_U300_I2C0 72 +#define IRQ_U300_I2C1 73 +#define IRQ_U300_RTC 74 +#define IRQ_U300_NFIF 75 +#define IRQ_U300_NFIF2 76 /* The DB3350-specific interrupt lines */ -#define IRQ_U300_ISP_F0 46 -#define IRQ_U300_ISP_F1 47 -#define IRQ_U300_ISP_F2 48 -#define IRQ_U300_ISP_F3 49 -#define IRQ_U300_ISP_F4 50 -#define IRQ_U300_GPIO_PORT3 51 -#define IRQ_U300_SYSCON_PLL_LOCK 52 -#define IRQ_U300_UART1 53 -#define IRQ_U300_GPIO_PORT4 54 -#define IRQ_U300_GPIO_PORT5 55 -#define IRQ_U300_GPIO_PORT6 56 -#define U300_VIC_IRQS_END 57 - -/* Maximum 8*7 GPIO lines */ -#ifdef CONFIG_PINCTRL_COH901 -#define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END) -#define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56) -#else -#define IRQ_U300_GPIO_END (U300_VIC_IRQS_END) -#endif - -#define NR_IRQS_U300 (IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START) +#define IRQ_U300_ISP_F0 77 +#define IRQ_U300_ISP_F1 78 +#define IRQ_U300_ISP_F2 79 +#define IRQ_U300_ISP_F3 80 +#define IRQ_U300_ISP_F4 81 +#define IRQ_U300_GPIO_PORT3 82 +#define IRQ_U300_SYSCON_PLL_LOCK 83 +#define IRQ_U300_UART1 84 +#define IRQ_U300_GPIO_PORT4 85 +#define IRQ_U300_GPIO_PORT5 86 +#define IRQ_U300_GPIO_PORT6 87 +#define U300_VIC_IRQS_END 88 #endif diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c index 070629a95625a9b7f3a5bfd0921d419a779966fc..33631c9f121802d447ecd38fa7f6bee4af955e18 100644 --- a/arch/arm/mach-ux500/board-mop500-audio.c +++ b/arch/arm/mach-ux500/board-mop500-audio.c @@ -7,9 +7,8 @@ #include #include #include +#include -#include -#include #include #include diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index a267c6d30e374f19c491244ad23fd93b07aa85d1..c34d4efd0d5c46987775b47c1393349760d60c27 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -9,10 +9,9 @@ #include #include #include +#include #include -#include -#include #include diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 416d436111f29bbc64c267f104ab2838cf3db0ac..0a3dd601a400c4cddeba32a945d2461bde52797a 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -37,13 +37,13 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index bcdfe6b1d4534e72dc952cfa989a98ac57d84b70..113d9c47a8428ffebf8d40e6e2e762de61f80640 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -17,14 +17,14 @@ #include #include #include +#include +#include #include #include -#include #include #include #include -#include #include #include "devices-db8500.h" @@ -158,7 +158,7 @@ static void __init db8500_add_gpios(struct device *parent) dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base), IRQ_DB8500_GPIO0, &pdata); - dbx500_add_pinctrl(parent, "pinctrl-db8500"); + dbx500_add_pinctrl(parent, "pinctrl-db8500", U8500_PRCMU_BASE); } static int usb_db8500_rx_dma_cfg[] = { diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index dfdd4a54668dfb4c85dfdb9a703f714b40a69bdc..692a77a1c1536eb045b714559b17d0e68aac78de 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -11,8 +11,7 @@ #include #include #include - -#include +#include #include diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 7fbf0ba336e1bba5e5f92cd2a0945ec411e5c5e6..96fa4ac89e2ecbee38e672dd8858679c7e09134c 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -129,12 +129,18 @@ void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num, int irq, struct nmk_gpio_platform_data *pdata); static inline void -dbx500_add_pinctrl(struct device *parent, const char *name) +dbx500_add_pinctrl(struct device *parent, const char *name, + resource_size_t base) { + struct resource res[] = { + DEFINE_RES_MEM(base, SZ_8K), + }; struct platform_device_info pdevinfo = { .parent = parent, .name = name, .id = -1, + .res = res, + .num_res = ARRAY_SIZE(res), }; platform_device_register_full(&pdevinfo); diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h deleted file mode 100644 index c08a54d9d8897dd686462787d8d205206e00da84..0000000000000000000000000000000000000000 --- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Structures and registers for GPIO access in the Nomadik SoC - * - * Copyright (C) 2008 STMicroelectronics - * Author: Prafulla WADASKAR - * Copyright (C) 2009 Alessandro Rubini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __PLAT_NOMADIK_GPIO -#define __PLAT_NOMADIK_GPIO - -/* - * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving - * the "gpio" namespace for generic and cross-machine functions - */ - -/* Register in the logic block */ -#define NMK_GPIO_DAT 0x00 -#define NMK_GPIO_DATS 0x04 -#define NMK_GPIO_DATC 0x08 -#define NMK_GPIO_PDIS 0x0c -#define NMK_GPIO_DIR 0x10 -#define NMK_GPIO_DIRS 0x14 -#define NMK_GPIO_DIRC 0x18 -#define NMK_GPIO_SLPC 0x1c -#define NMK_GPIO_AFSLA 0x20 -#define NMK_GPIO_AFSLB 0x24 -#define NMK_GPIO_LOWEMI 0x28 - -#define NMK_GPIO_RIMSC 0x40 -#define NMK_GPIO_FIMSC 0x44 -#define NMK_GPIO_IS 0x48 -#define NMK_GPIO_IC 0x4c -#define NMK_GPIO_RWIMSC 0x50 -#define NMK_GPIO_FWIMSC 0x54 -#define NMK_GPIO_WKS 0x58 - -/* Alternate functions: function C is set in hw by setting both A and B */ -#define NMK_GPIO_ALT_GPIO 0 -#define NMK_GPIO_ALT_A 1 -#define NMK_GPIO_ALT_B 2 -#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) - -#define NMK_GPIO_ALT_CX_SHIFT 2 -#define NMK_GPIO_ALT_C1 ((1< #include #include +#include #include /* Private data structure for of_gpiochip_find_and_xlate */ @@ -216,6 +217,54 @@ int of_mm_gpiochip_add(struct device_node *np, } EXPORT_SYMBOL(of_mm_gpiochip_add); +#ifdef CONFIG_PINCTRL +static void of_gpiochip_add_pin_range(struct gpio_chip *chip) +{ + struct device_node *np = chip->of_node; + struct of_phandle_args pinspec; + struct pinctrl_dev *pctldev; + int index = 0, ret; + + if (!np) + return; + + do { + ret = of_parse_phandle_with_args(np, "gpio-ranges", + "#gpio-range-cells", index, &pinspec); + if (ret) + break; + + pctldev = of_pinctrl_get(pinspec.np); + if (!pctldev) + break; + + /* + * This assumes that the n GPIO pins are consecutive in the + * GPIO number space, and that the pins are also consecutive + * in their local number space. Currently it is not possible + * to add different ranges for one and the same GPIO chip, + * as the code assumes that we have one consecutive range + * on both, mapping 1-to-1. + * + * TODO: make the OF bindings handle multiple sparse ranges + * on the same GPIO chip. + */ + ret = gpiochip_add_pin_range(chip, + pinctrl_dev_get_name(pctldev), + 0, /* offset in gpiochip */ + pinspec.args[0], + pinspec.args[1]); + + if (ret) + break; + + } while (index++); +} + +#else +static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {} +#endif + void of_gpiochip_add(struct gpio_chip *chip) { if ((!chip->of_node) && (chip->dev)) @@ -229,11 +278,14 @@ void of_gpiochip_add(struct gpio_chip *chip) chip->of_xlate = of_gpio_simple_xlate; } + of_gpiochip_add_pin_range(chip); of_node_get(chip->of_node); } void of_gpiochip_remove(struct gpio_chip *chip) { + gpiochip_remove_pin_ranges(chip); + if (chip->of_node) of_node_put(chip->of_node); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1c8d9e3380e17276e17e8f009659954e58d05bd1..58b9838801c0df3ca8568e7e9490297cc5bf68fe 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1083,6 +1083,10 @@ int gpiochip_add(struct gpio_chip *chip) } } +#ifdef CONFIG_PINCTRL + INIT_LIST_HEAD(&chip->pin_ranges); +#endif + of_gpiochip_add(chip); unlock: @@ -1123,6 +1127,7 @@ int gpiochip_remove(struct gpio_chip *chip) spin_lock_irqsave(&gpio_lock, flags); + gpiochip_remove_pin_ranges(chip); of_gpiochip_remove(chip); for (id = chip->base; id < chip->base + chip->ngpio; id++) { @@ -1180,6 +1185,77 @@ struct gpio_chip *gpiochip_find(void *data, } EXPORT_SYMBOL_GPL(gpiochip_find); +#ifdef CONFIG_PINCTRL + +/** + * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping + * @chip: the gpiochip to add the range for + * @pinctrl_name: the dev_name() of the pin controller to map to + * @gpio_offset: the start offset in the current gpio_chip number space + * @pin_offset: the start offset in the pin controller number space + * @npins: the number of pins from the offset of each pin space (GPIO and + * pin controller) to accumulate in this range + */ +int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, + unsigned int gpio_offset, unsigned int pin_offset, + unsigned int npins) +{ + struct gpio_pin_range *pin_range; + int ret; + + pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); + if (!pin_range) { + pr_err("%s: GPIO chip: failed to allocate pin ranges\n", + chip->label); + return -ENOMEM; + } + + /* Use local offset as range ID */ + pin_range->range.id = gpio_offset; + pin_range->range.gc = chip; + pin_range->range.name = chip->label; + pin_range->range.base = chip->base + gpio_offset; + pin_range->range.pin_base = pin_offset; + pin_range->range.npins = npins; + pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name, + &pin_range->range); + if (IS_ERR(pin_range->pctldev)) { + ret = PTR_ERR(pin_range->pctldev); + pr_err("%s: GPIO chip: could not create pin range\n", + chip->label); + kfree(pin_range); + return ret; + } + pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n", + chip->label, gpio_offset, gpio_offset + npins - 1, + pinctl_name, + pin_offset, pin_offset + npins - 1); + + list_add_tail(&pin_range->node, &chip->pin_ranges); + + return 0; +} +EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); + +/** + * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings + * @chip: the chip to remove all the mappings for + */ +void gpiochip_remove_pin_ranges(struct gpio_chip *chip) +{ + struct gpio_pin_range *pin_range, *tmp; + + list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) { + list_del(&pin_range->node); + pinctrl_remove_gpio_range(pin_range->pctldev, + &pin_range->range); + kfree(pin_range); + } +} +EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges); + +#endif /* CONFIG_PINCTRL */ + /* These "optional" allocation calls help prevent drivers from stomping * on each other, and help provide better diagnostics in debugfs. * They're called even less than the "set direction" calls. diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 9144557833027ad4cf1eeae236239bfc4a0a1c3b..92623ac2015a75fab52a8b6842a5a5b61572d547 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -1370,6 +1371,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) struct resource *mem; struct mtd_part_parser_data ppdata = {}; int res; + struct pinctrl *pinctrl; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { @@ -1414,6 +1416,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->IO_ADDR_W = host->io_base; nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + dev_err(host->dev, "Failed to request pinctrl\n"); + res = PTR_ERR(pinctrl); + goto err_ecc_ioremap; + } + if (gpio_is_valid(host->board.rdy_pin)) { res = gpio_request(host->board.rdy_pin, "nand_rdy"); if (res < 0) { diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index aeecf0f72cad50c633953e4ffd9617709239095b..390ab69ea5693443210e3e37b858d366179d5682 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -26,6 +26,15 @@ config DEBUG_PINCTRL help Say Y here to add some extra checks and diagnostics to PINCTRL calls. +config PINCTRL_AT91 + bool "AT91 pinctrl driver" + depends on OF + depends on ARCH_AT91 + select PINMUX + select PINCONF + help + Say Y here to enable the at91 pinctrl driver + config PINCTRL_BCM2835 bool select PINMUX @@ -87,21 +96,18 @@ config PINCTRL_MMP2 bool "MMP2 pin controller driver" depends on ARCH_MMP select PINCTRL_PXA3xx - select PINCONF config PINCTRL_MXS bool + select PINMUX + select PINCONF config PINCTRL_IMX23 bool - select PINMUX - select PINCONF select PINCTRL_MXS config PINCTRL_IMX28 bool - select PINMUX - select PINCONF select PINCTRL_MXS config PINCTRL_NOMADIK @@ -126,13 +132,11 @@ config PINCTRL_PXA168 bool "PXA168 pin controller driver" depends on ARCH_MMP select PINCTRL_PXA3xx - select PINCONF config PINCTRL_PXA910 bool "PXA910 pin controller driver" depends on ARCH_MMP select PINCTRL_PXA3xx - select PINCONF config PINCTRL_SINGLE tristate "One-register-per-pin type device tree based pinctrl driver" @@ -143,23 +147,21 @@ config PINCTRL_SINGLE This selects the device tree based generic pinctrl driver. config PINCTRL_SIRF - bool "CSR SiRFprimaII pin controller driver" - depends on ARCH_PRIMA2 + bool "CSR SiRFprimaII/SiRFmarco pin controller driver" + depends on ARCH_SIRF select PINMUX config PINCTRL_TEGRA bool + select PINMUX + select PINCONF config PINCTRL_TEGRA20 bool - select PINMUX - select PINCONF select PINCTRL_TEGRA config PINCTRL_TEGRA30 bool - select PINMUX - select PINCONF select PINCTRL_TEGRA config PINCTRL_U300 @@ -188,27 +190,7 @@ config PINCTRL_EXYNOS4 depends on OF && GPIOLIB select PINCTRL_SAMSUNG -config PINCTRL_MVEBU - bool - depends on ARCH_MVEBU - select PINMUX - select PINCONF - -config PINCTRL_DOVE - bool - select PINCTRL_MVEBU - -config PINCTRL_KIRKWOOD - bool - select PINCTRL_MVEBU - -config PINCTRL_ARMADA_370 - bool - select PINCTRL_MVEBU - -config PINCTRL_ARMADA_XP - bool - select PINCTRL_MVEBU +source "drivers/pinctrl/mvebu/Kconfig" source "drivers/pinctrl/spear/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f395ba5cec2579c4ab1372db251beaacf0f31491..f95f5ed923be9aff849fadc58cdcf54fb2f0a0d8 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -9,6 +9,7 @@ ifeq ($(CONFIG_OF),y) obj-$(CONFIG_PINCTRL) += devicetree.o endif obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o +obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o obj-$(CONFIG_PINCTRL_IMX35) += pinctrl-imx35.o @@ -36,12 +37,8 @@ obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.o -obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o -obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o -obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o -obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o -obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o +obj-$(CONFIG_PLAT_ORION) += mvebu/ obj-$(CONFIG_PLAT_SPEAR) += spear/ diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 2e39c04fc16bb4be31dba8800477aafed2e64441..5cdee8669ea35a8221e17c364e50df0d4c90c781 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -345,6 +345,62 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev, } EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges); +struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname, + struct pinctrl_gpio_range *range) +{ + struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname); + + /* + * If we can't find this device, let's assume that is because + * it has not probed yet, so the driver trying to register this + * range need to defer probing. + */ + if (!pctldev) + return ERR_PTR(-EPROBE_DEFER); + + pinctrl_add_gpio_range(pctldev, range); + return pctldev; +} +EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range); + +/** + * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin + * @pctldev: the pin controller device to look in + * @pin: a controller-local number to find the range for + */ +struct pinctrl_gpio_range * +pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, + unsigned int pin) +{ + struct pinctrl_gpio_range *range = NULL; + + /* Loop over the ranges */ + list_for_each_entry(range, &pctldev->gpio_ranges, node) { + /* Check if we're in the valid range */ + if (pin >= range->pin_base && + pin < range->pin_base + range->npins) { + return range; + } + } + + return NULL; +} +EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin); + +/** + * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller + * @pctldev: pin controller device to remove the range from + * @range: the GPIO range to remove + */ +void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range) +{ + mutex_lock(&pinctrl_mutex); + list_del(&range->node); + mutex_unlock(&pinctrl_mutex); +} +EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range); + /** * pinctrl_get_group_selector() - returns the group selector for a group * @pctldev: the pin controller handling the group @@ -563,6 +619,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) return -EPROBE_DEFER; } + setting->dev_name = map->dev_name; + switch (map->type) { case PIN_MAP_TYPE_MUX_GROUP: ret = pinmux_map_to_setting(map, setting); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 1f40ff68a8c406ff08234f463ebb3f088951e8f2..12f5694f3d5d9f02020cd2369603d6202e488b24 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -105,12 +105,14 @@ struct pinctrl_setting_configs { * @type: the type of setting * @pctldev: pin control device handling to be programmed. Not used for * PIN_MAP_TYPE_DUMMY_STATE. + * @dev_name: the name of the device using this state * @data: Data specific to the setting type */ struct pinctrl_setting { struct list_head node; enum pinctrl_map_type type; struct pinctrl_dev *pctldev; + const char *dev_name; union { struct pinctrl_setting_mux mux; struct pinctrl_setting_configs configs; diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index fcb1de45473cd2f7f6df93cbe28542b774f59ab3..fe2d1af7cfa0d0bce2eeb8a8391a4567da70bdd8 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -106,6 +106,17 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np) return NULL; } +struct pinctrl_dev *of_pinctrl_get(struct device_node *np) +{ + struct pinctrl_dev *pctldev; + + pctldev = find_pinctrl_by_of_node(np); + if (!pctldev) + return NULL; + + return pctldev; +} + static int dt_to_map_one_config(struct pinctrl *p, const char *statename, struct device_node *np_config) { diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..366fa541ee9121591e78f66c7ec4307a5d415203 --- /dev/null +++ b/drivers/pinctrl/mvebu/Kconfig @@ -0,0 +1,24 @@ +if PLAT_ORION + +config PINCTRL_MVEBU + bool + select PINMUX + select PINCONF + +config PINCTRL_DOVE + bool + select PINCTRL_MVEBU + +config PINCTRL_KIRKWOOD + bool + select PINCTRL_MVEBU + +config PINCTRL_ARMADA_370 + bool + select PINCTRL_MVEBU + +config PINCTRL_ARMADA_XP + bool + select PINCTRL_MVEBU + +endif diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..37c253297af004767252ec5c26eb8a4c75f19ef4 --- /dev/null +++ b/drivers/pinctrl/mvebu/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o +obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o +obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o +obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o +obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o diff --git a/drivers/pinctrl/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c similarity index 100% rename from drivers/pinctrl/pinctrl-armada-370.c rename to drivers/pinctrl/mvebu/pinctrl-armada-370.c diff --git a/drivers/pinctrl/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c similarity index 100% rename from drivers/pinctrl/pinctrl-armada-xp.c rename to drivers/pinctrl/mvebu/pinctrl-armada-xp.c diff --git a/drivers/pinctrl/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c similarity index 100% rename from drivers/pinctrl/pinctrl-dove.c rename to drivers/pinctrl/mvebu/pinctrl-dove.c diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c similarity index 100% rename from drivers/pinctrl/pinctrl-kirkwood.c rename to drivers/pinctrl/mvebu/pinctrl-kirkwood.c diff --git a/drivers/pinctrl/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c similarity index 99% rename from drivers/pinctrl/pinctrl-mvebu.c rename to drivers/pinctrl/mvebu/pinctrl-mvebu.c index 8e6266c6249aec67f79df210a375aa3f87aa5d7b..6c44b7e8964c48678d806f59a784da5c025ac993 100644 --- a/drivers/pinctrl/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -24,7 +24,6 @@ #include #include -#include "core.h" #include "pinctrl-mvebu.h" #define MPPS_PER_REG 8 diff --git a/drivers/pinctrl/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h similarity index 100% rename from drivers/pinctrl/pinctrl-mvebu.h rename to drivers/pinctrl/mvebu/pinctrl-mvebu.h diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 33fbaeaa65dd9dceecfa098ee3eec12f0413042e..833a36458157dd4c15ce0361ee84ced454cd93f4 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -41,6 +41,7 @@ struct pin_config_item conf_items[] = { PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL), PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL), PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL), + PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_DISABLE, "input schmitt disabled", NULL), PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL), PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"), PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"), diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c new file mode 100644 index 0000000000000000000000000000000000000000..c5e757157183de6ae7e084c46d82baec8fd7db4b --- /dev/null +++ b/drivers/pinctrl/pinctrl-at91.c @@ -0,0 +1,1634 @@ +/* + * at91 pinctrl driver based on at91 pinmux core + * + * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD + * + * Under GPLv2 only + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* Since we request GPIOs from ourself */ +#include + +#include + +#include +#include + +#include "core.h" + +#define MAX_NB_GPIO_PER_BANK 32 + +struct at91_pinctrl_mux_ops; + +struct at91_gpio_chip { + struct gpio_chip chip; + struct pinctrl_gpio_range range; + struct at91_gpio_chip *next; /* Bank sharing same clock */ + int pioc_hwirq; /* PIO bank interrupt identifier on AIC */ + int pioc_virq; /* PIO bank Linux virtual interrupt */ + int pioc_idx; /* PIO bank index */ + void __iomem *regbase; /* PIO bank virtual address */ + struct clk *clock; /* associated clock */ + struct irq_domain *domain; /* associated irq domain */ + struct at91_pinctrl_mux_ops *ops; /* ops */ +}; + +#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip) + +static struct at91_gpio_chip *gpio_chips[MAX_GPIO_BANKS]; + +static int gpio_banks; + +#define PULL_UP (1 << 0) +#define MULTI_DRIVE (1 << 1) +#define DEGLITCH (1 << 2) +#define PULL_DOWN (1 << 3) +#define DIS_SCHMIT (1 << 4) +#define DEBOUNCE (1 << 16) +#define DEBOUNCE_VAL_SHIFT 17 +#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT) + +/** + * struct at91_pmx_func - describes AT91 pinmux functions + * @name: the name of this specific function + * @groups: corresponding pin groups + * @ngroups: the number of groups + */ +struct at91_pmx_func { + const char *name; + const char **groups; + unsigned ngroups; +}; + +enum at91_mux { + AT91_MUX_GPIO = 0, + AT91_MUX_PERIPH_A = 1, + AT91_MUX_PERIPH_B = 2, + AT91_MUX_PERIPH_C = 3, + AT91_MUX_PERIPH_D = 4, +}; + +/** + * struct at91_pmx_pin - describes an At91 pin mux + * @bank: the bank of the pin + * @pin: the pin number in the @bank + * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function. + * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc... + */ +struct at91_pmx_pin { + uint32_t bank; + uint32_t pin; + enum at91_mux mux; + unsigned long conf; +}; + +/** + * struct at91_pin_group - describes an At91 pin group + * @name: the name of this specific pin group + * @pins_conf: the mux mode for each pin in this group. The size of this + * array is the same as pins. + * @pins: an array of discrete physical pins used in this group, taken + * from the driver-local pin enumeration space + * @npins: the number of pins in this group array, i.e. the number of + * elements in .pins so we can iterate over that array + */ +struct at91_pin_group { + const char *name; + struct at91_pmx_pin *pins_conf; + unsigned int *pins; + unsigned npins; +}; + +/** + * struct at91_pinctrl_mux_ops - describes an At91 mux ops group + * on new IP with support for periph C and D the way to mux in + * periph A and B has changed + * So provide the right call back + * if not present means the IP does not support it + * @get_periph: return the periph mode configured + * @mux_A_periph: mux as periph A + * @mux_B_periph: mux as periph B + * @mux_C_periph: mux as periph C + * @mux_D_periph: mux as periph D + * @get_deglitch: get deglitch status + * @set_deglitch: enable/disable deglitch + * @get_debounce: get debounce status + * @set_debounce: enable/disable debounce + * @get_pulldown: get pulldown status + * @set_pulldown: enable/disable pulldown + * @get_schmitt_trig: get schmitt trigger status + * @disable_schmitt_trig: disable schmitt trigger + * @irq_type: return irq type + */ +struct at91_pinctrl_mux_ops { + enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask); + void (*mux_A_periph)(void __iomem *pio, unsigned mask); + void (*mux_B_periph)(void __iomem *pio, unsigned mask); + void (*mux_C_periph)(void __iomem *pio, unsigned mask); + void (*mux_D_periph)(void __iomem *pio, unsigned mask); + bool (*get_deglitch)(void __iomem *pio, unsigned pin); + void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on); + bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div); + void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div); + bool (*get_pulldown)(void __iomem *pio, unsigned pin); + void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on); + bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin); + void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask); + /* irq */ + int (*irq_type)(struct irq_data *d, unsigned type); +}; + +static int gpio_irq_type(struct irq_data *d, unsigned type); +static int alt_gpio_irq_type(struct irq_data *d, unsigned type); + +struct at91_pinctrl { + struct device *dev; + struct pinctrl_dev *pctl; + + int nbanks; + + uint32_t *mux_mask; + int nmux; + + struct at91_pmx_func *functions; + int nfunctions; + + struct at91_pin_group *groups; + int ngroups; + + struct at91_pinctrl_mux_ops *ops; +}; + +static const inline struct at91_pin_group *at91_pinctrl_find_group_by_name( + const struct at91_pinctrl *info, + const char *name) +{ + const struct at91_pin_group *grp = NULL; + int i; + + for (i = 0; i < info->ngroups; i++) { + if (strcmp(info->groups[i].name, name)) + continue; + + grp = &info->groups[i]; + dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins, grp->pins[0]); + break; + } + + return grp; +} + +static int at91_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + return info->ngroups; +} + +static const char *at91_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + return info->groups[selector].name; +} + +static int at91_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, + const unsigned **pins, + unsigned *npins) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + if (selector >= info->ngroups) + return -EINVAL; + + *pins = info->groups[selector].pins; + *npins = info->groups[selector].npins; + + return 0; +} + +static void at91_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, + unsigned offset) +{ + seq_printf(s, "%s", dev_name(pctldev->dev)); +} + +static int at91_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, unsigned *num_maps) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + const struct at91_pin_group *grp; + struct pinctrl_map *new_map; + struct device_node *parent; + int map_num = 1; + int i; + + /* + * first find the group of this node and check if we need create + * config maps for pins + */ + grp = at91_pinctrl_find_group_by_name(info, np->name); + if (!grp) { + dev_err(info->dev, "unable to find group for node %s\n", + np->name); + return -EINVAL; + } + + map_num += grp->npins; + new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, GFP_KERNEL); + if (!new_map) + return -ENOMEM; + + *map = new_map; + *num_maps = map_num; + + /* create mux map */ + parent = of_get_parent(np); + if (!parent) { + kfree(new_map); + return -EINVAL; + } + new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; + new_map[0].data.mux.function = parent->name; + new_map[0].data.mux.group = np->name; + of_node_put(parent); + + /* create config map */ + new_map++; + for (i = 0; i < grp->npins; i++) { + new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN; + new_map[i].data.configs.group_or_pin = + pin_get_name(pctldev, grp->pins[i]); + new_map[i].data.configs.configs = &grp->pins_conf[i].conf; + new_map[i].data.configs.num_configs = 1; + } + + dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", + (*map)->data.mux.function, (*map)->data.mux.group, map_num); + + return 0; +} + +static void at91_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, unsigned num_maps) +{ +} + +static struct pinctrl_ops at91_pctrl_ops = { + .get_groups_count = at91_get_groups_count, + .get_group_name = at91_get_group_name, + .get_group_pins = at91_get_group_pins, + .pin_dbg_show = at91_pin_dbg_show, + .dt_node_to_map = at91_dt_node_to_map, + .dt_free_map = at91_dt_free_map, +}; + +static void __iomem * pin_to_controller(struct at91_pinctrl *info, + unsigned int bank) +{ + return gpio_chips[bank]->regbase; +} + +static inline int pin_to_bank(unsigned pin) +{ + return pin /= MAX_NB_GPIO_PER_BANK; +} + +static unsigned pin_to_mask(unsigned int pin) +{ + return 1 << pin; +} + +static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask) +{ + writel_relaxed(mask, pio + PIO_IDR); +} + +static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin) +{ + return (readl_relaxed(pio + PIO_PUSR) >> pin) & 0x1; +} + +static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on) +{ + writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR)); +} + +static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin) +{ + return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1; +} + +static void at91_mux_set_multidrive(void __iomem *pio, unsigned mask, bool on) +{ + writel_relaxed(mask, pio + (on ? PIO_MDER : PIO_MDDR)); +} + +static void at91_mux_set_A_periph(void __iomem *pio, unsigned mask) +{ + writel_relaxed(mask, pio + PIO_ASR); +} + +static void at91_mux_set_B_periph(void __iomem *pio, unsigned mask) +{ + writel_relaxed(mask, pio + PIO_BSR); +} + +static void at91_mux_pio3_set_A_periph(void __iomem *pio, unsigned mask) +{ + + writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask, + pio + PIO_ABCDSR1); + writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask, + pio + PIO_ABCDSR2); +} + +static void at91_mux_pio3_set_B_periph(void __iomem *pio, unsigned mask) +{ + writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask, + pio + PIO_ABCDSR1); + writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask, + pio + PIO_ABCDSR2); +} + +static void at91_mux_pio3_set_C_periph(void __iomem *pio, unsigned mask) +{ + writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1); + writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2); +} + +static void at91_mux_pio3_set_D_periph(void __iomem *pio, unsigned mask) +{ + writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1); + writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2); +} + +static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask) +{ + unsigned select; + + if (readl_relaxed(pio + PIO_PSR) & mask) + return AT91_MUX_GPIO; + + select = !!(readl_relaxed(pio + PIO_ABCDSR1) & mask); + select |= (!!(readl_relaxed(pio + PIO_ABCDSR2) & mask) << 1); + + return select + 1; +} + +static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask) +{ + unsigned select; + + if (readl_relaxed(pio + PIO_PSR) & mask) + return AT91_MUX_GPIO; + + select = readl_relaxed(pio + PIO_ABSR) & mask; + + return select + 1; +} + +static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin) +{ + return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1; +} + +static void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on) +{ + __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR)); +} + +static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on) +{ + if (is_on) + __raw_writel(mask, pio + PIO_IFSCDR); + at91_mux_set_deglitch(pio, mask, is_on); +} + +static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div) +{ + *div = __raw_readl(pio + PIO_SCDR); + + return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1; +} + +static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask, + bool is_on, u32 div) +{ + if (is_on) { + __raw_writel(mask, pio + PIO_IFSCER); + __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR); + __raw_writel(mask, pio + PIO_IFER); + } else { + __raw_writel(mask, pio + PIO_IFDR); + } +} + +static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin) +{ + return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1; +} + +static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on) +{ + __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR)); +} + +static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask) +{ + __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT); +} + +static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin) +{ + return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1; +} + +static struct at91_pinctrl_mux_ops at91rm9200_ops = { + .get_periph = at91_mux_get_periph, + .mux_A_periph = at91_mux_set_A_periph, + .mux_B_periph = at91_mux_set_B_periph, + .get_deglitch = at91_mux_get_deglitch, + .set_deglitch = at91_mux_set_deglitch, + .irq_type = gpio_irq_type, +}; + +static struct at91_pinctrl_mux_ops at91sam9x5_ops = { + .get_periph = at91_mux_pio3_get_periph, + .mux_A_periph = at91_mux_pio3_set_A_periph, + .mux_B_periph = at91_mux_pio3_set_B_periph, + .mux_C_periph = at91_mux_pio3_set_C_periph, + .mux_D_periph = at91_mux_pio3_set_D_periph, + .get_deglitch = at91_mux_get_deglitch, + .set_deglitch = at91_mux_pio3_set_deglitch, + .get_debounce = at91_mux_pio3_get_debounce, + .set_debounce = at91_mux_pio3_set_debounce, + .get_pulldown = at91_mux_pio3_get_pulldown, + .set_pulldown = at91_mux_pio3_set_pulldown, + .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig, + .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, + .irq_type = alt_gpio_irq_type, +}; + +static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin) +{ + if (pin->mux) { + dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lu\n", + pin->bank + 'A', pin->pin, pin->mux - 1 + 'A', pin->conf); + } else { + dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lu\n", + pin->bank + 'A', pin->pin, pin->conf); + } +} + +static int pin_check_config(struct at91_pinctrl *info, const char* name, + int index, const struct at91_pmx_pin *pin) +{ + int mux; + + /* check if it's a valid config */ + if (pin->bank >= info->nbanks) { + dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n", + name, index, pin->bank, info->nbanks); + return -EINVAL; + } + + if (pin->pin >= MAX_NB_GPIO_PER_BANK) { + dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n", + name, index, pin->pin, MAX_NB_GPIO_PER_BANK); + return -EINVAL; + } + + if (!pin->mux) + return 0; + + mux = pin->mux - 1; + + if (mux >= info->nmux) { + dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n", + name, index, mux, info->nmux); + return -EINVAL; + } + + if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) { + dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for pio%c%d\n", + name, index, mux, pin->bank + 'A', pin->pin); + return -EINVAL; + } + + return 0; +} + +static void at91_mux_gpio_disable(void __iomem *pio, unsigned mask) +{ + writel_relaxed(mask, pio + PIO_PDR); +} + +static void at91_mux_gpio_enable(void __iomem *pio, unsigned mask, bool input) +{ + writel_relaxed(mask, pio + PIO_PER); + writel_relaxed(mask, pio + (input ? PIO_ODR : PIO_OER)); +} + +static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf; + const struct at91_pmx_pin *pin; + uint32_t npins = info->groups[group].npins; + int i, ret; + unsigned mask; + void __iomem *pio; + + dev_dbg(info->dev, "enable function %s group %s\n", + info->functions[selector].name, info->groups[group].name); + + /* first check that all the pins of the group are valid with a valid + * paramter */ + for (i = 0; i < npins; i++) { + pin = &pins_conf[i]; + ret = pin_check_config(info, info->groups[group].name, i, pin); + if (ret) + return ret; + } + + for (i = 0; i < npins; i++) { + pin = &pins_conf[i]; + at91_pin_dbg(info->dev, pin); + pio = pin_to_controller(info, pin->bank); + mask = pin_to_mask(pin->pin); + at91_mux_disable_interrupt(pio, mask); + switch(pin->mux) { + case AT91_MUX_GPIO: + at91_mux_gpio_enable(pio, mask, 1); + break; + case AT91_MUX_PERIPH_A: + info->ops->mux_A_periph(pio, mask); + break; + case AT91_MUX_PERIPH_B: + info->ops->mux_B_periph(pio, mask); + break; + case AT91_MUX_PERIPH_C: + if (!info->ops->mux_C_periph) + return -EINVAL; + info->ops->mux_C_periph(pio, mask); + break; + case AT91_MUX_PERIPH_D: + if (!info->ops->mux_D_periph) + return -EINVAL; + info->ops->mux_D_periph(pio, mask); + break; + } + if (pin->mux) + at91_mux_gpio_disable(pio, mask); + } + + return 0; +} + +static void at91_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf; + const struct at91_pmx_pin *pin; + uint32_t npins = info->groups[group].npins; + int i; + unsigned mask; + void __iomem *pio; + + for (i = 0; i < npins; i++) { + pin = &pins_conf[i]; + at91_pin_dbg(info->dev, pin); + pio = pin_to_controller(info, pin->bank); + mask = pin_to_mask(pin->pin); + at91_mux_gpio_enable(pio, mask, 1); + } +} + +static int at91_pmx_get_funcs_count(struct pinctrl_dev *pctldev) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + return info->nfunctions; +} + +static const char *at91_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + return info->functions[selector].name; +} + +static int at91_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, + const char * const **groups, + unsigned * const num_groups) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + *groups = info->functions[selector].groups; + *num_groups = info->functions[selector].ngroups; + + return 0; +} + +static int at91_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + struct at91_gpio_chip *at91_chip; + struct gpio_chip *chip; + unsigned mask; + + if (!range) { + dev_err(npct->dev, "invalid range\n"); + return -EINVAL; + } + if (!range->gc) { + dev_err(npct->dev, "missing GPIO chip in range\n"); + return -EINVAL; + } + chip = range->gc; + at91_chip = container_of(chip, struct at91_gpio_chip, chip); + + dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset); + + mask = 1 << (offset - chip->base); + + dev_dbg(npct->dev, "enable pin %u as PIO%c%d 0x%x\n", + offset, 'A' + range->id, offset - chip->base, mask); + + writel_relaxed(mask, at91_chip->regbase + PIO_PER); + + return 0; +} + +static void at91_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset); + /* Set the pin to some default state, GPIO is usually default */ +} + +static struct pinmux_ops at91_pmx_ops = { + .get_functions_count = at91_pmx_get_funcs_count, + .get_function_name = at91_pmx_get_func_name, + .get_function_groups = at91_pmx_get_groups, + .enable = at91_pmx_enable, + .disable = at91_pmx_disable, + .gpio_request_enable = at91_gpio_request_enable, + .gpio_disable_free = at91_gpio_disable_free, +}; + +static int at91_pinconf_get(struct pinctrl_dev *pctldev, + unsigned pin_id, unsigned long *config) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + void __iomem *pio; + unsigned pin; + int div; + + dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config); + pio = pin_to_controller(info, pin_to_bank(pin_id)); + pin = pin_id % MAX_NB_GPIO_PER_BANK; + + if (at91_mux_get_multidrive(pio, pin)) + *config |= MULTI_DRIVE; + + if (at91_mux_get_pullup(pio, pin)) + *config |= PULL_UP; + + if (info->ops->get_deglitch && info->ops->get_deglitch(pio, pin)) + *config |= DEGLITCH; + if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div)) + *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT); + if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin)) + *config |= PULL_DOWN; + if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin)) + *config |= DIS_SCHMIT; + + return 0; +} + +static int at91_pinconf_set(struct pinctrl_dev *pctldev, + unsigned pin_id, unsigned long config) +{ + struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + unsigned mask; + void __iomem *pio; + + dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, config); + pio = pin_to_controller(info, pin_to_bank(pin_id)); + mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK); + + if (config & PULL_UP && config & PULL_DOWN) + return -EINVAL; + + at91_mux_set_pullup(pio, mask, config & PULL_UP); + at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE); + if (info->ops->set_deglitch) + info->ops->set_deglitch(pio, mask, config & DEGLITCH); + if (info->ops->set_debounce) + info->ops->set_debounce(pio, mask, config & DEBOUNCE, + (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT); + if (info->ops->set_pulldown) + info->ops->set_pulldown(pio, mask, config & PULL_DOWN); + if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT) + info->ops->disable_schmitt_trig(pio, mask); + + return 0; +} + +static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned pin_id) +{ + +} + +static void at91_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned group) +{ +} + +static struct pinconf_ops at91_pinconf_ops = { + .pin_config_get = at91_pinconf_get, + .pin_config_set = at91_pinconf_set, + .pin_config_dbg_show = at91_pinconf_dbg_show, + .pin_config_group_dbg_show = at91_pinconf_group_dbg_show, +}; + +static struct pinctrl_desc at91_pinctrl_desc = { + .pctlops = &at91_pctrl_ops, + .pmxops = &at91_pmx_ops, + .confops = &at91_pinconf_ops, + .owner = THIS_MODULE, +}; + +static const char *gpio_compat = "atmel,at91rm9200-gpio"; + +static void __devinit at91_pinctrl_child_count(struct at91_pinctrl *info, + struct device_node *np) +{ + struct device_node *child; + + for_each_child_of_node(np, child) { + if (of_device_is_compatible(child, gpio_compat)) { + info->nbanks++; + } else { + info->nfunctions++; + info->ngroups += of_get_child_count(child); + } + } +} + +static int __devinit at91_pinctrl_mux_mask(struct at91_pinctrl *info, + struct device_node *np) +{ + int ret = 0; + int size; + const const __be32 *list; + + list = of_get_property(np, "atmel,mux-mask", &size); + if (!list) { + dev_err(info->dev, "can not read the mux-mask of %d\n", size); + return -EINVAL; + } + + size /= sizeof(*list); + if (!size || size % info->nbanks) { + dev_err(info->dev, "wrong mux mask array should be by %d\n", info->nbanks); + return -EINVAL; + } + info->nmux = size / info->nbanks; + + info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL); + if (!info->mux_mask) { + dev_err(info->dev, "could not alloc mux_mask\n"); + return -ENOMEM; + } + + ret = of_property_read_u32_array(np, "atmel,mux-mask", + info->mux_mask, size); + if (ret) + dev_err(info->dev, "can not read the mux-mask of %d\n", size); + return ret; +} + +static int __devinit at91_pinctrl_parse_groups(struct device_node *np, + struct at91_pin_group *grp, + struct at91_pinctrl *info, + u32 index) +{ + struct at91_pmx_pin *pin; + int size; + const const __be32 *list; + int i, j; + + dev_dbg(info->dev, "group(%d): %s\n", index, np->name); + + /* Initialise group */ + grp->name = np->name; + + /* + * the binding format is atmel,pins = , + * do sanity check and calculate pins number + */ + list = of_get_property(np, "atmel,pins", &size); + /* we do not check return since it's safe node passed down */ + size /= sizeof(*list); + if (!size || size % 4) { + dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n"); + return -EINVAL; + } + + grp->npins = size / 4; + pin = grp->pins_conf = devm_kzalloc(info->dev, grp->npins * sizeof(struct at91_pmx_pin), + GFP_KERNEL); + grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), + GFP_KERNEL); + if (!grp->pins_conf || !grp->pins) + return -ENOMEM; + + for (i = 0, j = 0; i < size; i += 4, j++) { + pin->bank = be32_to_cpu(*list++); + pin->pin = be32_to_cpu(*list++); + grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin; + pin->mux = be32_to_cpu(*list++); + pin->conf = be32_to_cpu(*list++); + + at91_pin_dbg(info->dev, pin); + pin++; + } + + return 0; +} + +static int __devinit at91_pinctrl_parse_functions(struct device_node *np, + struct at91_pinctrl *info, u32 index) +{ + struct device_node *child; + struct at91_pmx_func *func; + struct at91_pin_group *grp; + int ret; + static u32 grp_index; + u32 i = 0; + + dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name); + + func = &info->functions[index]; + + /* Initialise function */ + func->name = np->name; + func->ngroups = of_get_child_count(np); + if (func->ngroups <= 0) { + dev_err(info->dev, "no groups defined\n"); + return -EINVAL; + } + func->groups = devm_kzalloc(info->dev, + func->ngroups * sizeof(char *), GFP_KERNEL); + if (!func->groups) + return -ENOMEM; + + for_each_child_of_node(np, child) { + func->groups[i] = child->name; + grp = &info->groups[grp_index++]; + ret = at91_pinctrl_parse_groups(child, grp, info, i++); + if (ret) + return ret; + } + + return 0; +} + +static struct of_device_id at91_pinctrl_of_match[] __devinitdata = { + { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops }, + { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops }, + { /* sentinel */ } +}; + +static int __devinit at91_pinctrl_probe_dt(struct platform_device *pdev, + struct at91_pinctrl *info) +{ + int ret = 0; + int i, j; + uint32_t *tmp; + struct device_node *np = pdev->dev.of_node; + struct device_node *child; + + if (!np) + return -ENODEV; + + info->dev = &pdev->dev; + info->ops = (struct at91_pinctrl_mux_ops*) + of_match_device(at91_pinctrl_of_match, &pdev->dev)->data; + at91_pinctrl_child_count(info, np); + + if (info->nbanks < 1) { + dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n"); + return -EINVAL; + } + + ret = at91_pinctrl_mux_mask(info, np); + if (ret) + return ret; + + dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux); + + dev_dbg(&pdev->dev, "mux-mask\n"); + tmp = info->mux_mask; + for (i = 0; i < info->nbanks; i++) { + for (j = 0; j < info->nmux; j++, tmp++) { + dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]); + } + } + + dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); + dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); + info->functions = devm_kzalloc(&pdev->dev, info->nfunctions * sizeof(struct at91_pmx_func), + GFP_KERNEL); + if (!info->functions) + return -ENOMEM; + + info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct at91_pin_group), + GFP_KERNEL); + if (!info->groups) + return -ENOMEM; + + dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks); + dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); + dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); + + i = 0; + + for_each_child_of_node(np, child) { + if (of_device_is_compatible(child, gpio_compat)) + continue; + ret = at91_pinctrl_parse_functions(child, info, i++); + if (ret) { + dev_err(&pdev->dev, "failed to parse function\n"); + return ret; + } + } + + return 0; +} + +static int __devinit at91_pinctrl_probe(struct platform_device *pdev) +{ + struct at91_pinctrl *info; + struct pinctrl_pin_desc *pdesc; + int ret, i, j ,k; + + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + ret = at91_pinctrl_probe_dt(pdev, info); + if (ret) + return ret; + + /* + * We need all the GPIO drivers to probe FIRST, or we will not be able + * to obtain references to the struct gpio_chip * for them, and we + * need this to proceed. + */ + for (i = 0; i < info->nbanks; i++) { + if (!gpio_chips[i]) { + dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i); + devm_kfree(&pdev->dev, info); + return -EPROBE_DEFER; + } + } + + at91_pinctrl_desc.name = dev_name(&pdev->dev); + at91_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK; + at91_pinctrl_desc.pins = pdesc = + devm_kzalloc(&pdev->dev, sizeof(*pdesc) * at91_pinctrl_desc.npins, GFP_KERNEL); + + if (!at91_pinctrl_desc.pins) + return -ENOMEM; + + for (i = 0 , k = 0; i < info->nbanks; i++) { + for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) { + pdesc->number = k; + pdesc->name = kasprintf(GFP_KERNEL, "pio%c%d", i + 'A', j); + pdesc++; + } + } + + platform_set_drvdata(pdev, info); + info->pctl = pinctrl_register(&at91_pinctrl_desc, &pdev->dev, info); + + if (!info->pctl) { + dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n"); + ret = -EINVAL; + goto err; + } + + /* We will handle a range of GPIO pins */ + for (i = 0; i < info->nbanks; i++) + pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range); + + dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n"); + + return 0; + +err: + return ret; +} + +static int __devexit at91_pinctrl_remove(struct platform_device *pdev) +{ + struct at91_pinctrl *info = platform_get_drvdata(pdev); + + pinctrl_unregister(info->pctl); + + return 0; +} + +static int at91_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + /* + * Map back to global GPIO space and request muxing, the direction + * parameter does not matter for this controller. + */ + int gpio = chip->base + offset; + int bank = chip->base / chip->ngpio; + + dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__, + 'A' + bank, offset, gpio); + + return pinctrl_request_gpio(gpio); +} + +static void at91_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + + pinctrl_free_gpio(gpio); +} + +static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << offset; + + writel_relaxed(mask, pio + PIO_ODR); + return 0; +} + +static int at91_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << offset; + u32 pdsr; + + pdsr = readl_relaxed(pio + PIO_PDSR); + return (pdsr & mask) != 0; +} + +static void at91_gpio_set(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << offset; + + writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR)); +} + +static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << offset; + + writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR)); + writel_relaxed(mask, pio + PIO_OER); + + return 0; +} + +static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); + int virq; + + if (offset < chip->ngpio) + virq = irq_create_mapping(at91_gpio->domain, offset); + else + virq = -ENXIO; + + dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n", + chip->label, offset + chip->base, virq); + return virq; +} + +#ifdef CONFIG_DEBUG_FS +static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + enum at91_mux mode; + int i; + struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); + void __iomem *pio = at91_gpio->regbase; + + for (i = 0; i < chip->ngpio; i++) { + unsigned pin = chip->base + i; + unsigned mask = pin_to_mask(pin); + const char *gpio_label; + u32 pdsr; + + gpio_label = gpiochip_is_requested(chip, i); + if (!gpio_label) + continue; + mode = at91_gpio->ops->get_periph(pio, mask); + seq_printf(s, "[%s] GPIO%s%d: ", + gpio_label, chip->label, i); + if (mode == AT91_MUX_GPIO) { + pdsr = readl_relaxed(pio + PIO_PDSR); + + seq_printf(s, "[gpio] %s\n", + pdsr & mask ? + "set" : "clear"); + } else { + seq_printf(s, "[periph %c]\n", + mode + 'A' - 1); + } + } +} +#else +#define at91_gpio_dbg_show NULL +#endif + +/* Several AIC controller irqs are dispatched through this GPIO handler. + * To use any AT91_PIN_* as an externally triggered IRQ, first call + * at91_set_gpio_input() then maybe enable its glitch filter. + * Then just request_irq() with the pin ID; it works like any ARM IRQ + * handler. + * First implementation always triggers on rising and falling edges + * whereas the newer PIO3 can be additionally configured to trigger on + * level, edge with any polarity. + * + * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after + * configuring them with at91_set_a_periph() or at91_set_b_periph(). + * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering. + */ + +static void gpio_irq_mask(struct irq_data *d) +{ + struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << d->hwirq; + + if (pio) + writel_relaxed(mask, pio + PIO_IDR); +} + +static void gpio_irq_unmask(struct irq_data *d) +{ + struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << d->hwirq; + + if (pio) + writel_relaxed(mask, pio + PIO_IER); +} + +static int gpio_irq_type(struct irq_data *d, unsigned type) +{ + switch (type) { + case IRQ_TYPE_NONE: + case IRQ_TYPE_EDGE_BOTH: + return 0; + default: + return -EINVAL; + } +} + +/* Alternate irq type for PIO3 support */ +static int alt_gpio_irq_type(struct irq_data *d, unsigned type) +{ + struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); + void __iomem *pio = at91_gpio->regbase; + unsigned mask = 1 << d->hwirq; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + writel_relaxed(mask, pio + PIO_ESR); + writel_relaxed(mask, pio + PIO_REHLSR); + break; + case IRQ_TYPE_EDGE_FALLING: + writel_relaxed(mask, pio + PIO_ESR); + writel_relaxed(mask, pio + PIO_FELLSR); + break; + case IRQ_TYPE_LEVEL_LOW: + writel_relaxed(mask, pio + PIO_LSR); + writel_relaxed(mask, pio + PIO_FELLSR); + break; + case IRQ_TYPE_LEVEL_HIGH: + writel_relaxed(mask, pio + PIO_LSR); + writel_relaxed(mask, pio + PIO_REHLSR); + break; + case IRQ_TYPE_EDGE_BOTH: + /* + * disable additional interrupt modes: + * fall back to default behavior + */ + writel_relaxed(mask, pio + PIO_AIMDR); + return 0; + case IRQ_TYPE_NONE: + default: + pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq)); + return -EINVAL; + } + + /* enable additional interrupt modes */ + writel_relaxed(mask, pio + PIO_AIMER); + + return 0; +} + +#ifdef CONFIG_PM +static int gpio_irq_set_wake(struct irq_data *d, unsigned state) +{ + struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); + unsigned bank = at91_gpio->pioc_idx; + + if (unlikely(bank >= MAX_GPIO_BANKS)) + return -EINVAL; + + irq_set_irq_wake(at91_gpio->pioc_virq, state); + + return 0; +} +#else +#define gpio_irq_set_wake NULL +#endif + +static struct irq_chip gpio_irqchip = { + .name = "GPIO", + .irq_disable = gpio_irq_mask, + .irq_mask = gpio_irq_mask, + .irq_unmask = gpio_irq_unmask, + /* .irq_set_type is set dynamically */ + .irq_set_wake = gpio_irq_set_wake, +}; + +static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct irq_data *idata = irq_desc_get_irq_data(desc); + struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata); + void __iomem *pio = at91_gpio->regbase; + unsigned long isr; + int n; + + chained_irq_enter(chip, desc); + for (;;) { + /* Reading ISR acks pending (edge triggered) GPIO interrupts. + * When there none are pending, we're finished unless we need + * to process multiple banks (like ID_PIOCDE on sam9263). + */ + isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR); + if (!isr) { + if (!at91_gpio->next) + break; + at91_gpio = at91_gpio->next; + pio = at91_gpio->regbase; + continue; + } + + for_each_set_bit(n, &isr, BITS_PER_LONG) { + generic_handle_irq(irq_find_mapping(at91_gpio->domain, n)); + } + } + chained_irq_exit(chip, desc); + /* now it may re-trigger */ +} + +/* + * This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ +static struct lock_class_key gpio_lock_class; + +static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct at91_gpio_chip *at91_gpio = h->host_data; + + irq_set_lockdep_class(virq, &gpio_lock_class); + + /* + * Can use the "simple" and not "edge" handler since it's + * shorter, and the AIC handles interrupts sanely. + */ + irq_set_chip_and_handler(virq, &gpio_irqchip, + handle_simple_irq); + set_irq_flags(virq, IRQF_VALID); + irq_set_chip_data(virq, at91_gpio); + + return 0; +} + +static int at91_gpio_irq_domain_xlate(struct irq_domain *d, + struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, + unsigned int *out_type) +{ + struct at91_gpio_chip *at91_gpio = d->host_data; + int ret; + int pin = at91_gpio->chip.base + intspec[0]; + + if (WARN_ON(intsize < 2)) + return -EINVAL; + *out_hwirq = intspec[0]; + *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; + + ret = gpio_request(pin, ctrlr->full_name); + if (ret) + return ret; + + ret = gpio_direction_input(pin); + if (ret) + return ret; + + return 0; +} + +static struct irq_domain_ops at91_gpio_ops = { + .map = at91_gpio_irq_map, + .xlate = at91_gpio_irq_domain_xlate, +}; + +static int at91_gpio_of_irq_setup(struct device_node *node, + struct at91_gpio_chip *at91_gpio) +{ + struct at91_gpio_chip *prev = NULL; + struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq); + + at91_gpio->pioc_hwirq = irqd_to_hwirq(d); + + /* Setup proper .irq_set_type function */ + gpio_irqchip.irq_set_type = at91_gpio->ops->irq_type; + + /* Disable irqs of this PIO controller */ + writel_relaxed(~0, at91_gpio->regbase + PIO_IDR); + + /* Setup irq domain */ + at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio, + &at91_gpio_ops, at91_gpio); + if (!at91_gpio->domain) + panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n", + at91_gpio->pioc_idx); + + /* Setup chained handler */ + if (at91_gpio->pioc_idx) + prev = gpio_chips[at91_gpio->pioc_idx - 1]; + + /* The toplevel handler handles one bank of GPIOs, except + * on some SoC it can handles up to three... + * We only set up the handler for the first of the list. + */ + if (prev && prev->next == at91_gpio) + return 0; + + irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio); + irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler); + + return 0; +} + +/* This structure is replicated for each GPIO block allocated at probe time */ +static struct gpio_chip at91_gpio_template = { + .request = at91_gpio_request, + .free = at91_gpio_free, + .direction_input = at91_gpio_direction_input, + .get = at91_gpio_get, + .direction_output = at91_gpio_direction_output, + .set = at91_gpio_set, + .to_irq = at91_gpio_to_irq, + .dbg_show = at91_gpio_dbg_show, + .can_sleep = 0, + .ngpio = MAX_NB_GPIO_PER_BANK, +}; + +static void __devinit at91_gpio_probe_fixup(void) +{ + unsigned i; + struct at91_gpio_chip *at91_gpio, *last = NULL; + + for (i = 0; i < gpio_banks; i++) { + at91_gpio = gpio_chips[i]; + + /* + * GPIO controller are grouped on some SoC: + * PIOC, PIOD and PIOE can share the same IRQ line + */ + if (last && last->pioc_virq == at91_gpio->pioc_virq) + last->next = at91_gpio; + last = at91_gpio; + } +} + +static struct of_device_id at91_gpio_of_match[] __devinitdata = { + { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, }, + { .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops }, + { /* sentinel */ } +}; + +static int __devinit at91_gpio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource *res; + struct at91_gpio_chip *at91_chip = NULL; + struct gpio_chip *chip; + struct pinctrl_gpio_range *range; + int ret = 0; + int irq, i; + int alias_idx = of_alias_get_id(np, "gpio"); + uint32_t ngpio; + char **names; + + BUG_ON(alias_idx >= ARRAY_SIZE(gpio_chips)); + if (gpio_chips[alias_idx]) { + ret = -EBUSY; + goto err; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENOENT; + goto err; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = irq; + goto err; + } + + at91_chip = devm_kzalloc(&pdev->dev, sizeof(*at91_chip), GFP_KERNEL); + if (!at91_chip) { + ret = -ENOMEM; + goto err; + } + + at91_chip->regbase = devm_request_and_ioremap(&pdev->dev, res); + if (!at91_chip->regbase) { + dev_err(&pdev->dev, "failed to map registers, ignoring.\n"); + ret = -EBUSY; + goto err; + } + + at91_chip->ops = (struct at91_pinctrl_mux_ops*) + of_match_device(at91_gpio_of_match, &pdev->dev)->data; + at91_chip->pioc_virq = irq; + at91_chip->pioc_idx = alias_idx; + + at91_chip->clock = clk_get(&pdev->dev, NULL); + if (IS_ERR(at91_chip->clock)) { + dev_err(&pdev->dev, "failed to get clock, ignoring.\n"); + goto err; + } + + if (clk_prepare(at91_chip->clock)) + goto clk_prep_err; + + /* enable PIO controller's clock */ + if (clk_enable(at91_chip->clock)) { + dev_err(&pdev->dev, "failed to enable clock, ignoring.\n"); + goto clk_err; + } + + at91_chip->chip = at91_gpio_template; + + chip = &at91_chip->chip; + chip->of_node = np; + chip->label = dev_name(&pdev->dev); + chip->dev = &pdev->dev; + chip->owner = THIS_MODULE; + chip->base = alias_idx * MAX_NB_GPIO_PER_BANK; + + if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) { + if (ngpio >= MAX_NB_GPIO_PER_BANK) + pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n", + alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK); + else + chip->ngpio = ngpio; + } + + names = devm_kzalloc(&pdev->dev, sizeof(char*) * chip->ngpio, GFP_KERNEL); + + if (!names) { + ret = -ENOMEM; + goto clk_err; + } + + for (i = 0; i < chip->ngpio; i++) + names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i); + + chip->names = (const char*const*)names; + + range = &at91_chip->range; + range->name = chip->label; + range->id = alias_idx; + range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK; + + range->npins = chip->ngpio; + range->gc = chip; + + ret = gpiochip_add(chip); + if (ret) + goto clk_err; + + gpio_chips[alias_idx] = at91_chip; + gpio_banks = max(gpio_banks, alias_idx + 1); + + at91_gpio_probe_fixup(); + + at91_gpio_of_irq_setup(np, at91_chip); + + dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase); + + return 0; + +clk_err: + clk_unprepare(at91_chip->clock); +clk_prep_err: + clk_put(at91_chip->clock); +err: + dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx); + + return ret; +} + +static struct platform_driver at91_gpio_driver = { + .driver = { + .name = "gpio-at91", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(at91_gpio_of_match), + }, + .probe = at91_gpio_probe, +}; + +static struct platform_driver at91_pinctrl_driver = { + .driver = { + .name = "pinctrl-at91", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(at91_pinctrl_of_match), + }, + .probe = at91_pinctrl_probe, + .remove = __devexit_p(at91_pinctrl_remove), +}; + +static int __init at91_pinctrl_init(void) +{ + int ret; + + ret = platform_driver_register(&at91_gpio_driver); + if (ret) + return ret; + return platform_driver_register(&at91_pinctrl_driver); +} +arch_initcall(at91_pinctrl_init); + +static void __exit at91_pinctrl_exit(void) +{ + platform_driver_unregister(&at91_pinctrl_driver); +} + +module_exit(at91_pinctrl_exit); +MODULE_AUTHOR("Jean-Christophe PLAGNIOL-VILLARD "); +MODULE_DESCRIPTION("Atmel AT91 pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c index 7e9be18ec2d2b92922373f7f62d8543d43febf50..9a963edd66d161f96d95131620247026689ebb87 100644 --- a/drivers/pinctrl/pinctrl-bcm2835.c +++ b/drivers/pinctrl/pinctrl-bcm2835.c @@ -916,7 +916,7 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev, return 0; } -struct pinconf_ops bcm2835_pinconf_ops = { +static struct pinconf_ops bcm2835_pinconf_ops = { .pin_config_get = bcm2835_pinconf_get, .pin_config_set = bcm2835_pinconf_set, }; diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c index b446c9641212884f8cb2ff5e7df0d81aa032dca3..fbb37154471cae9579acb0cceb3890047ac97bcc 100644 --- a/drivers/pinctrl/pinctrl-coh901.c +++ b/drivers/pinctrl/pinctrl-coh901.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -64,10 +65,8 @@ struct u300_gpio { struct gpio_chip chip; struct list_head port_list; struct clk *clk; - struct resource *memres; void __iomem *base; struct device *dev; - int irq_base; u32 stride; /* Register offsets */ u32 pcr; @@ -83,6 +82,7 @@ struct u300_gpio_port { struct list_head node; struct u300_gpio *gpio; char name[8]; + struct irq_domain *domain; int irq; int number; u8 toggle_edge_mode; @@ -314,10 +314,30 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset, static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { struct u300_gpio *gpio = to_u300_gpio(chip); - int retirq = gpio->irq_base + offset; + int portno = offset >> 3; + struct u300_gpio_port *port = NULL; + struct list_head *p; + int retirq; - dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset, - retirq); + list_for_each(p, &gpio->port_list) { + port = list_entry(p, struct u300_gpio_port, node); + if (port->number == portno) + break; + } + if (port == NULL) { + dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n", + offset); + return -EINVAL; + } + + /* + * The local hwirqs on the port are the lower three bits, there + * are exactly 8 IRQs per port since they are 8-bit + */ + retirq = irq_find_mapping(port->domain, (offset & 0x7)); + + dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n", + offset, retirq, port->number); return retirq; } @@ -467,7 +487,7 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger) { struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); struct u300_gpio *gpio = port->gpio; - int offset = d->irq - gpio->irq_base; + int offset = (port->number << 3) + d->hwirq; u32 val; if ((trigger & IRQF_TRIGGER_RISING) && @@ -503,10 +523,12 @@ static void u300_gpio_irq_enable(struct irq_data *d) { struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); struct u300_gpio *gpio = port->gpio; - int offset = d->irq - gpio->irq_base; + int offset = (port->number << 3) + d->hwirq; u32 val; unsigned long flags; + dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n", + d->hwirq, port->name, offset); local_irq_save(flags); val = readl(U300_PIN_REG(offset, ien)); writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); @@ -517,7 +539,7 @@ static void u300_gpio_irq_disable(struct irq_data *d) { struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); struct u300_gpio *gpio = port->gpio; - int offset = d->irq - gpio->irq_base; + int offset = (port->number << 3) + d->hwirq; u32 val; unsigned long flags; @@ -555,8 +577,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) int irqoffset; for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) { - int pin_irq = gpio->irq_base + (port->number << 3) - + irqoffset; + int pin_irq = irq_find_mapping(port->domain, irqoffset); int offset = pinoffset + irqoffset; dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n", @@ -631,64 +652,86 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio) list_for_each_safe(p, n, &gpio->port_list) { port = list_entry(p, struct u300_gpio_port, node); list_del(&port->node); + if (port->domain) + irq_domain_remove(port->domain); kfree(port); } } +/* + * Here we map a GPIO in the local gpio_chip pin space to a pin in + * the local pinctrl pin space. The pin controller used is + * pinctrl-u300. + */ +struct coh901_pinpair { + unsigned int offset; + unsigned int pin_base; +}; + +#define COH901_PINRANGE(a, b) { .offset = a, .pin_base = b } + +static struct coh901_pinpair coh901_pintable[] = { + COH901_PINRANGE(10, 426), + COH901_PINRANGE(11, 180), + COH901_PINRANGE(12, 165), /* MS/MMC card insertion */ + COH901_PINRANGE(13, 179), + COH901_PINRANGE(14, 178), + COH901_PINRANGE(16, 194), + COH901_PINRANGE(17, 193), + COH901_PINRANGE(18, 192), + COH901_PINRANGE(19, 191), + COH901_PINRANGE(20, 186), + COH901_PINRANGE(21, 185), + COH901_PINRANGE(22, 184), + COH901_PINRANGE(23, 183), + COH901_PINRANGE(24, 182), + COH901_PINRANGE(25, 181), +}; + static int __init u300_gpio_probe(struct platform_device *pdev) { struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev); struct u300_gpio *gpio; + struct resource *memres; int err = 0; int portno; u32 val; u32 ifr; int i; - gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL); - if (gpio == NULL) { - dev_err(&pdev->dev, "failed to allocate memory\n"); + gpio = devm_kzalloc(&pdev->dev, sizeof(struct u300_gpio), GFP_KERNEL); + if (gpio == NULL) return -ENOMEM; - } gpio->chip = u300_gpio_chip; gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT; - gpio->irq_base = plat->gpio_irq_base; gpio->chip.dev = &pdev->dev; gpio->chip.base = plat->gpio_base; gpio->dev = &pdev->dev; - /* Get GPIO clock */ - gpio->clk = clk_get(gpio->dev, NULL); + memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!memres) { + dev_err(gpio->dev, "could not get GPIO memory resource\n"); + return -ENODEV; + } + + gpio->base = devm_request_and_ioremap(&pdev->dev, memres); + if (!gpio->base) { + dev_err(gpio->dev, "could not get remap memory\n"); + return -ENOMEM; + } + + gpio->clk = devm_clk_get(gpio->dev, NULL); if (IS_ERR(gpio->clk)) { err = PTR_ERR(gpio->clk); dev_err(gpio->dev, "could not get GPIO clock\n"); - goto err_no_clk; + return err; } + err = clk_prepare_enable(gpio->clk); if (err) { dev_err(gpio->dev, "could not enable GPIO clock\n"); - goto err_no_clk_enable; - } - - gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!gpio->memres) { - dev_err(gpio->dev, "could not get GPIO memory resource\n"); - err = -ENODEV; - goto err_no_resource; - } - - if (!request_mem_region(gpio->memres->start, - resource_size(gpio->memres), - "GPIO Controller")) { - err = -ENODEV; - goto err_no_ioregion; - } - - gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres)); - if (!gpio->base) { - err = -ENOMEM; - goto err_no_ioremap; + return err; } dev_info(gpio->dev, @@ -732,18 +775,28 @@ static int __init u300_gpio_probe(struct platform_device *pdev) port->irq = platform_get_irq_byname(pdev, port->name); - dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq, + dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq, port->name); + port->domain = irq_domain_add_linear(pdev->dev.of_node, + U300_GPIO_PINS_PER_PORT, + &irq_domain_simple_ops, + port); + if (!port->domain) { + err = -ENOMEM; + goto err_no_domain; + } + irq_set_chained_handler(port->irq, u300_gpio_irq_handler); irq_set_handler_data(port->irq, port); /* For each GPIO pin set the unique IRQ handler */ for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) { - int irqno = gpio->irq_base + (portno << 3) + i; + int irqno = irq_create_mapping(port->domain, i); - dev_dbg(gpio->dev, "handler for IRQ %d on %s\n", - irqno, port->name); + dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n", + gpio->chip.base + (port->number << 3) + i, + port->name, irqno); irq_set_chip_and_handler(irqno, &u300_gpio_irqchip, handle_simple_irq); set_irq_flags(irqno, IRQF_VALID); @@ -763,32 +816,31 @@ static int __init u300_gpio_probe(struct platform_device *pdev) goto err_no_chip; } - /* Spawn pin controller device as child of the GPIO, pass gpio chip */ - plat->pinctrl_device->dev.platform_data = &gpio->chip; - err = platform_device_register(plat->pinctrl_device); - if (err) - goto err_no_pinctrl; + /* + * Add pinctrl pin ranges, the pin controller must be registered + * at this point + */ + for (i = 0; i < ARRAY_SIZE(coh901_pintable); i++) { + struct coh901_pinpair *p = &coh901_pintable[i]; + + err = gpiochip_add_pin_range(&gpio->chip, "pinctrl-u300", + p->offset, p->pin_base, 1); + if (err) + goto err_no_range; + } platform_set_drvdata(pdev, gpio); return 0; -err_no_pinctrl: +err_no_range: err = gpiochip_remove(&gpio->chip); err_no_chip: +err_no_domain: err_no_port: u300_gpio_free_ports(gpio); - iounmap(gpio->base); -err_no_ioremap: - release_mem_region(gpio->memres->start, resource_size(gpio->memres)); -err_no_ioregion: -err_no_resource: clk_disable_unprepare(gpio->clk); -err_no_clk_enable: - clk_put(gpio->clk); -err_no_clk: - kfree(gpio); - dev_info(&pdev->dev, "module ERROR:%d\n", err); + dev_err(&pdev->dev, "module ERROR:%d\n", err); return err; } @@ -806,13 +858,8 @@ static int __exit u300_gpio_remove(struct platform_device *pdev) return err; } u300_gpio_free_ports(gpio); - iounmap(gpio->base); - release_mem_region(gpio->memres->start, - resource_size(gpio->memres)); clk_disable_unprepare(gpio->clk); - clk_put(gpio->clk); platform_set_drvdata(pdev, NULL); - kfree(gpio); return 0; } diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 21362f48d3700424244b2870cbfa0cb437af6f66..6ff665209a4cf6a05cd3fdbaef51b5302ca5063d 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -36,6 +36,7 @@ /* list of external wakeup controllers supported */ static const struct of_device_id exynos_wkup_irq_ids[] = { { .compatible = "samsung,exynos4210-wakeup-eint", }, + { } }; static void exynos_gpio_irq_unmask(struct irq_data *irqd) diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c index ee730590347057b9260a304487f217caf17e4671..8ed20e84cb0274f486264c8d00e1d5ff5c86edee 100644 --- a/drivers/pinctrl/pinctrl-falcon.c +++ b/drivers/pinctrl/pinctrl-falcon.c @@ -322,7 +322,7 @@ static void falcon_pinconf_group_dbg_show(struct pinctrl_dev *pctrldev, { } -struct pinconf_ops falcon_pinconf_ops = { +static struct pinconf_ops falcon_pinconf_ops = { .pin_config_get = falcon_pinconf_get, .pin_config_set = falcon_pinconf_set, .pin_config_group_get = falcon_pinconf_group_get, diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c index 63866d95357ddb9692ed7692f7e682424199b9e6..525a2c8644f62a0fff0fae171efbcced284498ec 100644 --- a/drivers/pinctrl/pinctrl-imx.c +++ b/drivers/pinctrl/pinctrl-imx.c @@ -71,7 +71,7 @@ static const struct imx_pin_reg *imx_find_pin_reg( break; } - if (!pin_reg) { + if (i == info->npin_regs) { dev_err(info->dev, "Pin(%s): unable to find pin reg map\n", info->pins[pin].name); return NULL; @@ -397,7 +397,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, } } -struct pinconf_ops imx_pinconf_ops = { +static struct pinconf_ops imx_pinconf_ops = { .pin_config_get = imx_pinconf_get, .pin_config_set = imx_pinconf_set, .pin_config_dbg_show = imx_pinconf_dbg_show, diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c index 07ba7682cf22f57547ad471ae1933dc43c572daa..15f501d89026f2360cf59639c464e5200f5e03c8 100644 --- a/drivers/pinctrl/pinctrl-lantiq.c +++ b/drivers/pinctrl/pinctrl-lantiq.c @@ -46,8 +46,8 @@ static int ltq_get_group_pins(struct pinctrl_dev *pctrldev, return 0; } -void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, - struct pinctrl_map *map, unsigned num_maps) +static void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, unsigned num_maps) { int i; @@ -128,10 +128,10 @@ static int ltq_pinctrl_dt_subnode_size(struct device_node *np) return ret; } -int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *np_config, - struct pinctrl_map **map, - unsigned *num_maps) +static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, + unsigned *num_maps) { struct pinctrl_map *tmp; struct device_node *np; @@ -275,16 +275,6 @@ static int ltq_pmx_enable(struct pinctrl_dev *pctrldev, return 0; } -static void ltq_pmx_disable(struct pinctrl_dev *pctrldev, - unsigned func, - unsigned group) -{ - /* - * Nothing to do here. However, pinconf_check_ops() requires this - * callback to be defined. - */ -} - static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev, struct pinctrl_gpio_range *range, unsigned pin) @@ -312,7 +302,6 @@ static struct pinmux_ops ltq_pmx_ops = { .get_function_name = ltq_pmx_func_name, .get_function_groups = ltq_pmx_get_groups, .enable = ltq_pmx_enable, - .disable = ltq_pmx_disable, .gpio_request_enable = ltq_pmx_gpio_request_enable, }; diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c index 4ba4636b6a4ac6b67d30b366299b2452bb983b76..3e7d4d63f8bf8e49d1d2c88fbe3c187ad66d955e 100644 --- a/drivers/pinctrl/pinctrl-mxs.c +++ b/drivers/pinctrl/pinctrl-mxs.c @@ -319,7 +319,7 @@ static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, "0x%lx", config); } -struct pinconf_ops mxs_pinconf_ops = { +static struct pinconf_ops mxs_pinconf_ops = { .pin_config_get = mxs_pinconf_get, .pin_config_set = mxs_pinconf_set, .pin_config_group_get = mxs_pinconf_group_get, diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c index debaa75b0552d6daeefc24e4d5ee4dd929baca76..7d88ae35211976f2db4372aa6d377822651524d4 100644 --- a/drivers/pinctrl/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c @@ -475,8 +475,10 @@ static const unsigned hsit_a_1_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9, DB8500_PIN_AG9, DB8500_PIN_AG8, DB8500_PIN_AF8 }; static const unsigned hsit_a_2_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9, DB8500_PIN_AG9, DB8500_PIN_AG8 }; -static const unsigned clkout_a_1_pins[] = { DB8500_PIN_AH7, DB8500_PIN_AJ6 }; -static const unsigned clkout_a_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 }; +static const unsigned clkout1_a_1_pins[] = { DB8500_PIN_AH7 }; +static const unsigned clkout1_a_2_pins[] = { DB8500_PIN_AG7 }; +static const unsigned clkout2_a_1_pins[] = { DB8500_PIN_AJ6 }; +static const unsigned clkout2_a_2_pins[] = { DB8500_PIN_AF7 }; static const unsigned usb_a_1_pins[] = { DB8500_PIN_AF28, DB8500_PIN_AE29, DB8500_PIN_AD29, DB8500_PIN_AC29, DB8500_PIN_AD28, DB8500_PIN_AD26, DB8500_PIN_AE26, DB8500_PIN_AG29, DB8500_PIN_AE27, DB8500_PIN_AD27, @@ -592,7 +594,8 @@ static const unsigned stmmod_c_1_pins[] = { DB8500_PIN_C20, DB8500_PIN_B21, DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24 }; static const unsigned usbsim_c_1_pins[] = { DB8500_PIN_D22 }; static const unsigned mc4rstn_c_1_pins[] = { DB8500_PIN_AF25 }; -static const unsigned clkout_c_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12 }; +static const unsigned clkout1_c_1_pins[] = { DB8500_PIN_AH13 }; +static const unsigned clkout2_c_1_pins[] = { DB8500_PIN_AH12 }; static const unsigned i2c3_c_1_pins[] = { DB8500_PIN_AG12, DB8500_PIN_AH11 }; static const unsigned spi0_c_1_pins[] = { DB8500_PIN_AH10, DB8500_PIN_AH9, DB8500_PIN_AG9, DB8500_PIN_AG8 }; @@ -600,14 +603,66 @@ static const unsigned usbsim_c_2_pins[] = { DB8500_PIN_AF8 }; static const unsigned i2c3_c_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 }; /* Other C1 column */ +static const unsigned u2rx_oc1_1_pins[] = { DB8500_PIN_AB2 }; +static const unsigned stmape_oc1_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4, + DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 }; +static const unsigned remap0_oc1_1_pins[] = { DB8500_PIN_E1 }; +static const unsigned remap1_oc1_1_pins[] = { DB8500_PIN_E2 }; +static const unsigned ptma9_oc1_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2, + DB8500_PIN_J2, DB8500_PIN_H1 }; static const unsigned kp_oc1_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3, DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6, DB8500_PIN_D6, DB8500_PIN_B7 }; +static const unsigned rf_oc1_1_pins[] = { DB8500_PIN_D8, DB8500_PIN_D9 }; +static const unsigned hxclk_oc1_1_pins[] = { DB8500_PIN_D16 }; +static const unsigned uartmodrx_oc1_1_pins[] = { DB8500_PIN_B17 }; +static const unsigned uartmodtx_oc1_1_pins[] = { DB8500_PIN_C16 }; +static const unsigned stmmod_oc1_1_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 }; +static const unsigned hxgpio_oc1_1_pins[] = { DB8500_PIN_D21, DB8500_PIN_D20, + DB8500_PIN_C20, DB8500_PIN_B21, DB8500_PIN_C21, DB8500_PIN_A22, + DB8500_PIN_B24, DB8500_PIN_C22 }; +static const unsigned rf_oc1_2_pins[] = { DB8500_PIN_C23, DB8500_PIN_D23 }; static const unsigned spi2_oc1_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12, DB8500_PIN_AH12, DB8500_PIN_AH11 }; static const unsigned spi2_oc1_2_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12, DB8500_PIN_AH11 }; +/* Other C2 column */ +static const unsigned sbag_oc2_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_AB2, + DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 }; +static const unsigned etmr4_oc2_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2, + DB8500_PIN_J2, DB8500_PIN_H1 }; +static const unsigned ptma9_oc2_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16, + DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20, + DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 }; + +/* Other C3 column */ +static const unsigned stmmod_oc3_1_pins[] = { DB8500_PIN_AB2, DB8500_PIN_W2, + DB8500_PIN_W3, DB8500_PIN_V3, DB8500_PIN_V2 }; +static const unsigned stmmod_oc3_2_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 }; +static const unsigned uartmodrx_oc3_1_pins[] = { DB8500_PIN_H2 }; +static const unsigned uartmodtx_oc3_1_pins[] = { DB8500_PIN_J2 }; +static const unsigned etmr4_oc3_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16, + DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20, + DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 }; + +/* Other C4 column */ +static const unsigned sbag_oc4_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H1 }; +static const unsigned hwobs_oc4_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16, + DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20, + DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 }; + #define DB8500_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins, \ .npins = ARRAY_SIZE(a##_pins), .altsetting = b } @@ -639,6 +694,7 @@ static const struct nmk_pingroup nmk_db8500_groups[] = { DB8500_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(kp_a_2, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(msp2_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A), @@ -647,8 +703,10 @@ static const struct nmk_pingroup nmk_db8500_groups[] = { DB8500_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A), - DB8500_PIN_GROUP(clkout_a_1, NMK_GPIO_ALT_A), - DB8500_PIN_GROUP(clkout_a_2, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A), /* Altfunction B column */ DB8500_PIN_GROUP(trig_b_1, NMK_GPIO_ALT_B), @@ -720,15 +778,41 @@ static const struct nmk_pingroup nmk_db8500_groups[] = { DB8500_PIN_GROUP(stmmod_c_1, NMK_GPIO_ALT_C), DB8500_PIN_GROUP(usbsim_c_1, NMK_GPIO_ALT_C), DB8500_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C), - DB8500_PIN_GROUP(clkout_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(clkout1_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(clkout2_c_1, NMK_GPIO_ALT_C), DB8500_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C), DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C), DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C), DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C), /* Other alt C1 column */ + DB8500_PIN_GROUP(u2rx_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(ptma9_oc1_1, NMK_GPIO_ALT_C1), DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(rf_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(hxclk_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(uartmodrx_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(uartmodtx_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(stmmod_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(hxgpio_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(rf_oc1_2, NMK_GPIO_ALT_C1), DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1), DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1), + /* Other alt C2 column */ + DB8500_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2), + DB8500_PIN_GROUP(etmr4_oc2_1, NMK_GPIO_ALT_C2), + DB8500_PIN_GROUP(ptma9_oc2_1, NMK_GPIO_ALT_C2), + /* Other alt C3 column */ + DB8500_PIN_GROUP(stmmod_oc3_1, NMK_GPIO_ALT_C3), + DB8500_PIN_GROUP(stmmod_oc3_2, NMK_GPIO_ALT_C3), + DB8500_PIN_GROUP(uartmodrx_oc3_1, NMK_GPIO_ALT_C3), + DB8500_PIN_GROUP(uartmodtx_oc3_1, NMK_GPIO_ALT_C3), + DB8500_PIN_GROUP(etmr4_oc3_1, NMK_GPIO_ALT_C3), + /* Other alt C4 column */ + DB8500_PIN_GROUP(sbag_oc4_1, NMK_GPIO_ALT_C4), + DB8500_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4), }; /* We use this macro to define the groups applicable to a function */ @@ -742,7 +826,7 @@ DB8500_FUNC_GROUPS(u1, "u1rxtx_a_1", "u1ctsrts_a_1"); * only available on two pins in alternative function C */ DB8500_FUNC_GROUPS(u2, "u2rxtx_b_1", "u2rxtx_c_1", "u2ctsrts_c_1", - "u2rxtx_c_2", "u2rxtx_c_3"); + "u2rxtx_c_2", "u2rxtx_c_3", "u2rx_oc1_1"); DB8500_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2"); /* * MSP0 can only be on a certain set of pins, but the TX/RX pins can be @@ -757,7 +841,7 @@ DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1"); DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1"); DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1", "lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1"); -DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1"); +DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_a_2", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1"); DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1"); DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1"); DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1"); @@ -773,7 +857,8 @@ DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1"); DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1"); DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2", "mc1dir_a_1"); DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2"); -DB8500_FUNC_GROUPS(clkout, "clkout_a_1", "clkout_a_2", "clkout_c_1"); +DB8500_FUNC_GROUPS(clkout, "clkout1_a_1", "clkout1_a_2", "clkout1_c_1", + "clkout2_a_1", "clkout2_a_2", "clkout2_c_1"); DB8500_FUNC_GROUPS(usb, "usb_a_1"); DB8500_FUNC_GROUPS(trig, "trig_b_1"); DB8500_FUNC_GROUPS(i2c4, "i2c4_b_1"); @@ -784,8 +869,10 @@ DB8500_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2"); * so select one of each. */ DB8500_FUNC_GROUPS(uartmod, "uartmodtx_b_1", "uartmodrx_b_1", "uartmodrx_b_2", - "uartmodrx_c_1", "uartmod_tx_c_1"); -DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1"); + "uartmodrx_c_1", "uartmod_tx_c_1", "uartmodrx_oc1_1", + "uartmodtx_oc1_1", "uartmodrx_oc3_1", "uartmodtx_oc3_1"); +DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1", "stmmod_oc1_1", + "stmmod_oc3_1", "stmmod_oc3_2"); DB8500_FUNC_GROUPS(spi3, "spi3_b_1"); /* Select between CS0 on alt B or PS1 on alt C */ DB8500_FUNC_GROUPS(sm, "sm_b_1", "smcs0_b_1", "smcs1_b_1", "smcleale_c_1", @@ -799,13 +886,19 @@ DB8500_FUNC_GROUPS(ipjtag, "ipjtag_c_1"); DB8500_FUNC_GROUPS(slim0, "slim0_c_1"); DB8500_FUNC_GROUPS(ms, "ms_c_1"); DB8500_FUNC_GROUPS(iptrigout, "iptrigout_c_1"); -DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2"); +DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2", "stmape_oc1_1"); DB8500_FUNC_GROUPS(mc5, "mc5_c_1"); DB8500_FUNC_GROUPS(usbsim, "usbsim_c_1", "usbsim_c_2"); DB8500_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c3_c_2"); DB8500_FUNC_GROUPS(spi0, "spi0_c_1"); DB8500_FUNC_GROUPS(spi2, "spi2_oc1_1", "spi2_oc1_2"); - +DB8500_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1"); +DB8500_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc4_1"); +DB8500_FUNC_GROUPS(ptm, "ptma9_oc1_1", "ptma9_oc2_1"); +DB8500_FUNC_GROUPS(rf, "rf_oc1_1", "rf_oc1_2"); +DB8500_FUNC_GROUPS(hx, "hxclk_oc1_1", "hxgpio_oc1_1"); +DB8500_FUNC_GROUPS(etm, "etmr4_oc2_1", "etmr4_oc3_1"); +DB8500_FUNC_GROUPS(hwobs, "hwobs_oc4_1"); #define FUNCTION(fname) \ { \ .name = #fname, \ @@ -858,6 +951,12 @@ static const struct nmk_function nmk_db8500_functions[] = { FUNCTION(i2c3), FUNCTION(spi0), FUNCTION(spi2), + FUNCTION(remap), + FUNCTION(ptm), + FUNCTION(rf), + FUNCTION(hx), + FUNCTION(etm), + FUNCTION(hwobs), }; static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = { diff --git a/drivers/pinctrl/pinctrl-nomadik-db8540.c b/drivers/pinctrl/pinctrl-nomadik-db8540.c index 52fc30181f7ea908848a48a6d095373a1d1619d6..bb6a4016322aa7daa1ee7063127557cb5eb52a1d 100644 --- a/drivers/pinctrl/pinctrl-nomadik-db8540.c +++ b/drivers/pinctrl/pinctrl-nomadik-db8540.c @@ -460,8 +460,10 @@ static const unsigned hsit_a_1_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10, DB8540_PIN_E10, DB8540_PIN_B12, DB8540_PIN_D10 }; static const unsigned hsit_a_2_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10, DB8540_PIN_E10, DB8540_PIN_B12 }; -static const unsigned clkout_a_1_pins[] = { DB8540_PIN_D11, DB8540_PIN_AJ6 }; -static const unsigned clkout_a_2_pins[] = { DB8540_PIN_B13, DB8540_PIN_C12 }; +static const unsigned clkout1_a_1_pins[] = { DB8540_PIN_D11 }; +static const unsigned clkout1_a_2_pins[] = { DB8540_PIN_B13 }; +static const unsigned clkout2_a_1_pins[] = { DB8540_PIN_AJ6 }; +static const unsigned clkout2_a_2_pins[] = { DB8540_PIN_C12 }; static const unsigned msp4_a_1_pins[] = { DB8540_PIN_B14, DB8540_PIN_E11 }; static const unsigned usb_a_1_pins[] = { DB8540_PIN_D12, DB8540_PIN_D15, DB8540_PIN_C13, DB8540_PIN_C14, DB8540_PIN_C18, DB8540_PIN_C16, @@ -698,8 +700,10 @@ static const struct nmk_pingroup nmk_db8540_groups[] = { DB8540_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A), DB8540_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A), DB8540_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A), - DB8540_PIN_GROUP(clkout_a_1, NMK_GPIO_ALT_A), - DB8540_PIN_GROUP(clkout_a_2, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A), DB8540_PIN_GROUP(msp4_a_1, NMK_GPIO_ALT_A), DB8540_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A), /* Altfunction B column */ @@ -822,6 +826,7 @@ static const struct nmk_pingroup nmk_db8540_groups[] = { DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4), DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4), DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4), + DB8540_PIN_GROUP(moduartstmmux_oc4_1, NMK_GPIO_ALT_C4), }; @@ -830,7 +835,8 @@ static const struct nmk_pingroup nmk_db8540_groups[] = { static const char * const a##_groups[] = { b }; DB8540_FUNC_GROUPS(apetrig, "apetrig_b_1"); -DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout_a_1", "clkout_a_2"); +DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout1_a_1", "clkout1_a_2", + "clkout2_a_1", "clkout2_a_2"); DB8540_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1"); DB8540_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2"); DB8540_FUNC_GROUPS(hwobs, "hwobs_oc4_1"); diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index cf82d9ce4deeccc8c19c6104103fee84854c945a..8ef3e85cb011ef5928e1668ea901cf1236784cbd 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -30,26 +30,10 @@ #include /* Since we request GPIOs from ourself */ #include -/* - * For the U8500 archs, use the PRCMU register interface, for the older - * Nomadik, provide some stubs. The functions using these will only be - * called on the U8500 series. - */ -#ifdef CONFIG_ARCH_U8500 -#include -#else -static inline u32 prcmu_read(unsigned int reg) { - return 0; -} -static inline void prcmu_write(unsigned int reg, u32 value) {} -static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {} -#endif +#include #include -#include -#include - #include "pinctrl-nomadik.h" /* @@ -60,8 +44,6 @@ static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {} * Symbols in this file are called "nmk_gpio" for "nomadik gpio" */ -#define NMK_GPIO_PER_CHIP 32 - struct nmk_gpio_chip { struct gpio_chip chip; struct irq_domain *domain; @@ -86,10 +68,18 @@ struct nmk_gpio_chip { u32 lowemi; }; +/** + * struct nmk_pinctrl - state container for the Nomadik pin controller + * @dev: containing device pointer + * @pctl: corresponding pin controller device + * @soc: SoC data for this specific chip + * @prcm_base: PRCM register range virtual base + */ struct nmk_pinctrl { struct device *dev; struct pinctrl_dev *pctl; const struct nmk_pinctrl_soc_data *soc; + void __iomem *prcm_base; }; static struct nmk_gpio_chip * @@ -251,6 +241,15 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset) dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio); } +static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value) +{ + u32 val; + + val = readl(reg); + val = ((val & ~mask) | (value & mask)); + writel(val, reg); +} + static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, unsigned offset, unsigned alt_num) { @@ -289,8 +288,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, if (pin_desc->altcx[i].used == true) { reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; bit = pin_desc->altcx[i].control_bit; - if (prcmu_read(reg) & BIT(bit)) { - prcmu_write_masked(reg, BIT(bit), 0); + if (readl(npct->prcm_base + reg) & BIT(bit)) { + nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0); dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n", offset, i+1); @@ -318,8 +317,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, if (pin_desc->altcx[i].used == true) { reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; bit = pin_desc->altcx[i].control_bit; - if (prcmu_read(reg) & BIT(bit)) { - prcmu_write_masked(reg, BIT(bit), 0); + if (readl(npct->prcm_base + reg) & BIT(bit)) { + nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0); dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n", offset, i+1); @@ -331,7 +330,7 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, bit = pin_desc->altcx[alt_index].control_bit; dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n", offset, alt_index+1); - prcmu_write_masked(reg, BIT(bit), BIT(bit)); + nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit)); } static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, @@ -536,7 +535,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) * and its sleep mode based on the specified configuration. The @cfg is * usually one of the SoC specific macros defined in mach/-pins.h. These * are constructed using, and can be further enhanced with, the macros in - * plat/pincfg.h. + * * * If a pin's mode is set to GPIO, it is configured as an input to avoid * side-effects. The gpio can be manipulated later using standard GPIO API @@ -675,6 +674,35 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode) } EXPORT_SYMBOL(nmk_gpio_set_mode); +static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio) +{ + int i; + u16 reg; + u8 bit; + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + const struct prcm_gpiocr_altcx_pin_desc *pin_desc; + const u16 *gpiocr_regs; + + for (i = 0; i < npct->soc->npins_altcx; i++) { + if (npct->soc->altcx_pins[i].pin == gpio) + break; + } + if (i == npct->soc->npins_altcx) + return NMK_GPIO_ALT_C; + + pin_desc = npct->soc->altcx_pins + i; + gpiocr_regs = npct->soc->prcm_gpiocr_registers; + for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) { + if (pin_desc->altcx[i].used == true) { + reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; + bit = pin_desc->altcx[i].control_bit; + if (readl(npct->prcm_base + reg) & BIT(bit)) + return NMK_GPIO_ALT_C+i+1; + } + } + return NMK_GPIO_ALT_C; +} + int nmk_gpio_get_mode(int gpio) { struct nmk_gpio_chip *nmk_chip; @@ -1063,8 +1091,9 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) #include -static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip, - unsigned offset, unsigned gpio) +static void nmk_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, struct gpio_chip *chip, + unsigned offset, unsigned gpio) { const char *label = gpiochip_is_requested(chip, offset); struct nmk_gpio_chip *nmk_chip = @@ -1078,12 +1107,18 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip, [NMK_GPIO_ALT_A] = "altA", [NMK_GPIO_ALT_B] = "altB", [NMK_GPIO_ALT_C] = "altC", + [NMK_GPIO_ALT_C+1] = "altC1", + [NMK_GPIO_ALT_C+2] = "altC2", + [NMK_GPIO_ALT_C+3] = "altC3", + [NMK_GPIO_ALT_C+4] = "altC4", }; clk_enable(nmk_chip->clk); is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit); pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit); mode = nmk_gpio_get_mode(gpio); + if ((mode == NMK_GPIO_ALT_C) && pctldev) + mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio); seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s", gpio, label ?: "(none)", @@ -1127,13 +1162,14 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) unsigned gpio = chip->base; for (i = 0; i < chip->ngpio; i++, gpio++) { - nmk_gpio_dbg_show_one(s, chip, i, gpio); + nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio); seq_printf(s, "\n"); } } #else static inline void nmk_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, struct gpio_chip *chip, unsigned offset, unsigned gpio) { @@ -1250,8 +1286,8 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up) } } -int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) +static int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) { struct nmk_gpio_chip *nmk_chip = d->host_data; @@ -1464,7 +1500,7 @@ static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, return; } chip = range->gc; - nmk_gpio_dbg_show_one(s, chip, offset - chip->base, offset); + nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); } static struct pinctrl_ops nmk_pinctrl_ops = { @@ -1635,9 +1671,9 @@ static void nmk_pmx_disable(struct pinctrl_dev *pctldev, dev_dbg(npct->dev, "disable group %s, %u pins\n", g->name, g->npins); } -int nmk_gpio_request_enable(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, - unsigned offset) +static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) { struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); struct nmk_gpio_chip *nmk_chip; @@ -1666,9 +1702,9 @@ int nmk_gpio_request_enable(struct pinctrl_dev *pctldev, return 0; } -void nmk_gpio_disable_free(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, - unsigned offset) +static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) { struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); @@ -1686,17 +1722,15 @@ static struct pinmux_ops nmk_pinmux_ops = { .gpio_disable_free = nmk_gpio_disable_free, }; -int nmk_pin_config_get(struct pinctrl_dev *pctldev, - unsigned pin, - unsigned long *config) +static int nmk_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config) { /* Not implemented */ return -EINVAL; } -int nmk_pin_config_set(struct pinctrl_dev *pctldev, - unsigned pin, - unsigned long config) +static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long config) { static const char *pullnames[] = { [NMK_GPIO_PULL_NONE] = "none", @@ -1818,6 +1852,7 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) const struct platform_device_id *platid = platform_get_device_id(pdev); struct device_node *np = pdev->dev.of_node; struct nmk_pinctrl *npct; + struct resource *res; unsigned int version = 0; int i; @@ -1827,9 +1862,14 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) if (platid) version = platid->driver_data; - else if (np) - version = (unsigned int) - of_match_device(nmk_pinctrl_match, &pdev->dev)->data; + else if (np) { + const struct of_device_id *match; + + match = of_match_device(nmk_pinctrl_match, &pdev->dev); + if (!match) + return -ENODEV; + version = (unsigned int) match->data; + } /* Poke in other ASIC variants here */ if (version == PINCTRL_NMK_STN8815) @@ -1839,22 +1879,37 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) if (version == PINCTRL_NMK_DB8540) nmk_pinctrl_db8540_init(&npct->soc); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + npct->prcm_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!npct->prcm_base) { + dev_err(&pdev->dev, + "failed to ioremap PRCM registers\n"); + return -ENOMEM; + } + } else { + dev_info(&pdev->dev, + "No PRCM base, assume no ALT-Cx control is available\n"); + } + /* * We need all the GPIO drivers to probe FIRST, or we will not be able * to obtain references to the struct gpio_chip * for them, and we * need this to proceed. */ for (i = 0; i < npct->soc->gpio_num_ranges; i++) { - if (!nmk_gpio_chips[i]) { + if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) { dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i); return -EPROBE_DEFER; } - npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip; + npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip; } nmk_pinctrl_desc.pins = npct->soc->pins; nmk_pinctrl_desc.npins = npct->soc->npins; npct->dev = &pdev->dev; + npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct); if (!npct->pctl) { dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n"); @@ -1889,6 +1944,7 @@ static const struct platform_device_id nmk_pinctrl_id[] = { { "pinctrl-stn8815", PINCTRL_NMK_STN8815 }, { "pinctrl-db8500", PINCTRL_NMK_DB8500 }, { "pinctrl-db8540", PINCTRL_NMK_DB8540 }, + { } }; static struct platform_driver nmk_pinctrl_driver = { diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/pinctrl-nomadik.h index eef316e979a02a1156c8ede6ca10c3b039e5d7fc..bcd4191e10ea8ced278c469799d521e4a82dee65 100644 --- a/drivers/pinctrl/pinctrl-nomadik.h +++ b/drivers/pinctrl/pinctrl-nomadik.h @@ -1,7 +1,7 @@ #ifndef PINCTRL_PINCTRL_NOMADIK_H #define PINCTRL_PINCTRL_NOMADIK_H -#include +#include /* Package definitions */ #define PINCTRL_NMK_STN8815 0 diff --git a/drivers/pinctrl/pinctrl-pxa3xx.c b/drivers/pinctrl/pinctrl-pxa3xx.c index f14cd6ba4c0b7ffa8c8bfb75b474c585757d2e74..51f8a388b917a991eb1cba5ca2d1c08973ed4076 100644 --- a/drivers/pinctrl/pinctrl-pxa3xx.c +++ b/drivers/pinctrl/pinctrl-pxa3xx.c @@ -173,7 +173,6 @@ int pxa3xx_pinctrl_register(struct platform_device *pdev, { struct pinctrl_desc *desc; struct resource *res; - int ret = 0; if (!info || !info->cputype) return -EINVAL; @@ -188,23 +187,17 @@ int pxa3xx_pinctrl_register(struct platform_device *pdev, res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENOENT; - info->phy_base = res->start; - info->phy_size = resource_size(res); - info->virt_base = ioremap(info->phy_base, info->phy_size); + info->virt_base = devm_request_and_ioremap(&pdev->dev, res); if (!info->virt_base) return -ENOMEM; info->pctrl = pinctrl_register(desc, &pdev->dev, info); if (!info->pctrl) { dev_err(&pdev->dev, "failed to register PXA pinmux driver\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range); platform_set_drvdata(pdev, info); return 0; -err: - iounmap(info->virt_base); - return ret; } int pxa3xx_pinctrl_unregister(struct platform_device *pdev) @@ -212,7 +205,6 @@ int pxa3xx_pinctrl_unregister(struct platform_device *pdev) struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev); pinctrl_unregister(info->pctrl); - iounmap(info->virt_base); platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/pinctrl/pinctrl-pxa3xx.h b/drivers/pinctrl/pinctrl-pxa3xx.h index 8135744d6599baf8fbf6d04f9aee91d8219cd143..92fad08808348606755c55fdb0ee15508b7ca7d6 100644 --- a/drivers/pinctrl/pinctrl-pxa3xx.h +++ b/drivers/pinctrl/pinctrl-pxa3xx.h @@ -60,8 +60,6 @@ struct pxa3xx_pinmux_info { struct device *dev; struct pinctrl_dev *pctrl; enum pxa_cpu_type cputype; - unsigned int phy_base; - unsigned int phy_size; void __iomem *virt_base; struct pxa3xx_mfp_pin *mfp; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 726a729a2ec92d5d0ae5e45e94bd458305496219..554946356fba5f27464b3fed8b04b5e6522bf6c2 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -30,6 +30,7 @@ #define PCS_MUX_BITS_NAME "pinctrl-single,bits" #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1) #define PCS_OFF_DISABLED ~0U +#define PCS_MAX_GPIO_VALUES 2 /** * struct pcs_pingroup - pingroups for a function @@ -76,6 +77,16 @@ struct pcs_function { struct list_head node; }; +/** + * struct pcs_gpio_range - pinctrl gpio range + * @range: subrange of the GPIO number space + * @gpio_func: gpio function value in the pinmux register + */ +struct pcs_gpio_range { + struct pinctrl_gpio_range range; + int gpio_func; +}; + /** * struct pcs_data - wrapper for data needed by pinctrl framework * @pa: pindesc array @@ -244,15 +255,15 @@ static int pcs_get_group_pins(struct pinctrl_dev *pctldev, static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, - unsigned offset) + unsigned pin) { struct pcs_device *pcs; - unsigned val; + unsigned val, mux_bytes; pcs = pinctrl_dev_get_drvdata(pctldev); - val = pcs->read(pcs->base + offset); - val &= pcs->fmask; + mux_bytes = pcs->width / BITS_PER_BYTE; + val = pcs->read(pcs->base + pin * mux_bytes); seq_printf(s, "%08x %s " , val, DRIVER_NAME); } @@ -403,9 +414,26 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector, } static int pcs_request_gpio(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, unsigned offset) + struct pinctrl_gpio_range *range, unsigned pin) { - return -ENOTSUPP; + struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev); + struct pcs_gpio_range *gpio = NULL; + int end, mux_bytes; + unsigned data; + + gpio = container_of(range, struct pcs_gpio_range, range); + end = range->pin_base + range->npins - 1; + if (pin < range->pin_base || pin > end) { + dev_err(pctldev->dev, + "pin %d isn't in the range of %d to %d\n", + pin, range->pin_base, end); + return -EINVAL; + } + mux_bytes = pcs->width / BITS_PER_BYTE; + data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask; + data |= gpio->gpio_func; + pcs->write(data, pcs->base + pin * mux_bytes); + return 0; } static struct pinmux_ops pcs_pinmux_ops = { @@ -772,7 +800,7 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev, pcs = pinctrl_dev_get_drvdata(pctldev); *map = devm_kzalloc(pcs->dev, sizeof(**map), GFP_KERNEL); - if (!map) + if (!*map) return -ENOMEM; *num_maps = 0; @@ -879,6 +907,50 @@ static void pcs_free_resources(struct pcs_device *pcs) static struct of_device_id pcs_of_match[]; +static int __devinit pcs_add_gpio_range(struct device_node *node, + struct pcs_device *pcs) +{ + struct pcs_gpio_range *gpio; + struct device_node *child; + struct resource r; + const char name[] = "pinctrl-single"; + u32 gpiores[PCS_MAX_GPIO_VALUES]; + int ret, i = 0, mux_bytes = 0; + + for_each_child_of_node(node, child) { + ret = of_address_to_resource(child, 0, &r); + if (ret < 0) + continue; + memset(gpiores, 0, sizeof(u32) * PCS_MAX_GPIO_VALUES); + ret = of_property_read_u32_array(child, "pinctrl-single,gpio", + gpiores, PCS_MAX_GPIO_VALUES); + if (ret < 0) + continue; + gpio = devm_kzalloc(pcs->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) { + dev_err(pcs->dev, "failed to allocate pcs gpio\n"); + return -ENOMEM; + } + gpio->range.name = devm_kzalloc(pcs->dev, sizeof(name), + GFP_KERNEL); + if (!gpio->range.name) { + dev_err(pcs->dev, "failed to allocate range name\n"); + return -ENOMEM; + } + memcpy((char *)gpio->range.name, name, sizeof(name)); + + gpio->range.id = i++; + gpio->range.base = gpiores[0]; + gpio->gpio_func = gpiores[1]; + mux_bytes = pcs->width / BITS_PER_BYTE; + gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes; + gpio->range.npins = (r.end - r.start) / mux_bytes + 1; + + pinctrl_add_gpio_range(pcs->pctl, &gpio->range); + } + return 0; +} + static int __devinit pcs_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -975,6 +1047,10 @@ static int __devinit pcs_probe(struct platform_device *pdev) goto free; } + ret = pcs_add_gpio_range(np, pcs); + if (ret < 0) + goto free; + dev_info(pcs->dev, "%i pins at pa %p size %u\n", pcs->desc.npins, pcs->base, pcs->size); diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 9ecacf3d0a759715db3d1081677747b51905626f..a3905e58d1b395de11923f3fc2ea759de9f8f059 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -32,10 +32,10 @@ #define SIRFSOC_NUM_PADS 622 #define SIRFSOC_RSC_PIN_MUX 0x4 -#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84) +#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84) +#define SIRFSOC_GPIO_PAD_EN_CLR(g) ((g)*0x100 + 0x90) #define SIRFSOC_GPIO_CTRL(g, i) ((g)*0x100 + (i)*4) #define SIRFSOC_GPIO_DSP_EN0 (0x80) -#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84) #define SIRFSOC_GPIO_INT_STATUS(g) ((g)*0x100 + 0x8C) #define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1 @@ -60,6 +60,7 @@ struct sirfsoc_gpio_bank { int id; int parent_irq; spinlock_t lock; + bool is_marco; /* for marco, some registers are different with prima2 */ }; static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS]; @@ -191,6 +192,7 @@ struct sirfsoc_pmx { struct pinctrl_dev *pmx; void __iomem *gpio_virtbase; void __iomem *rsc_virtbase; + bool is_marco; }; /* SIRFSOC_GPIO_PAD_EN set */ @@ -1088,12 +1090,21 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector for (i = 0; i < mux->muxmask_counts; i++) { u32 muxval; - muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group)); - if (enable) - muxval = muxval & ~mask[i].mask; - else - muxval = muxval | mask[i].mask; - writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group)); + if (!spmx->is_marco) { + muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group)); + if (enable) + muxval = muxval & ~mask[i].mask; + else + muxval = muxval | mask[i].mask; + writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group)); + } else { + if (enable) + writel(mask[i].mask, spmx->gpio_virtbase + + SIRFSOC_GPIO_PAD_EN_CLR(mask[i].group)); + else + writel(mask[i].mask, spmx->gpio_virtbase + + SIRFSOC_GPIO_PAD_EN(mask[i].group)); + } } if (mux->funcmask && enable) { @@ -1158,9 +1169,14 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev, spmx = pinctrl_dev_get_drvdata(pmxdev); - muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); - muxval = muxval | (1 << (offset - range->pin_base)); - writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); + if (!spmx->is_marco) { + muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); + muxval = muxval | (1 << (offset - range->pin_base)); + writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); + } else { + writel(1 << (offset - range->pin_base), spmx->gpio_virtbase + + SIRFSOC_GPIO_PAD_EN(group)); + } return 0; } @@ -1218,6 +1234,7 @@ static void __iomem *sirfsoc_rsc_of_iomap(void) { const struct of_device_id rsc_ids[] = { { .compatible = "sirf,prima2-rsc" }, + { .compatible = "sirf,marco-rsc" }, {} }; struct device_node *np; @@ -1259,6 +1276,9 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev) goto out_no_rsc_remap; } + if (of_device_is_compatible(np, "sirf,marco-pinctrl")) + spmx->is_marco = 1; + /* Now register the pin controller and all pins it handles */ spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx); if (!spmx->pmx) { @@ -1287,6 +1307,7 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev) static const struct of_device_id pinmux_ids[] __devinitconst = { { .compatible = "sirf,prima2-pinctrl" }, + { .compatible = "sirf,marco-pinctrl" }, {} }; @@ -1621,8 +1642,8 @@ static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset, spin_unlock_irqrestore(&bank->lock, flags); } -int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) +static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) { struct sirfsoc_gpio_bank *bank = d->host_data; @@ -1648,6 +1669,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np) struct sirfsoc_gpio_bank *bank; void *regs; struct platform_device *pdev; + bool is_marco = false; pdev = of_find_device_by_node(np); if (!pdev) @@ -1657,6 +1679,9 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np) if (!regs) return -ENOMEM; + if (of_device_is_compatible(np, "sirf,marco-pinctrl")) + is_marco = 1; + for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { bank = &sgpio_bank[i]; spin_lock_init(&bank->lock); @@ -1673,6 +1698,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np) bank->chip.gc.of_node = np; bank->chip.regs = regs; bank->id = i; + bank->is_marco = is_marco; bank->parent_irq = platform_get_irq(pdev, i); if (bank->parent_irq < 0) { err = bank->parent_irq; diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index 7da0b371fd652a04ac7d55ecf89c55c915d19f8b..e9f80a54b3d0c4077f0b54d94efc98928d72aaf5 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -178,8 +178,9 @@ static int add_config(struct device *dev, unsigned long **configs, return 0; } -void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, - struct pinctrl_map *map, unsigned num_maps) +static void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, + unsigned num_maps) { int i; @@ -209,11 +210,11 @@ static const struct cfg_param { {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, }; -int tegra_pinctrl_dt_subnode_to_map(struct device *dev, - struct device_node *np, - struct pinctrl_map **map, - unsigned *reserved_maps, - unsigned *num_maps) +static int tegra_pinctrl_dt_subnode_to_map(struct device *dev, + struct device_node *np, + struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps) { int ret, i; const char *function; @@ -288,9 +289,10 @@ int tegra_pinctrl_dt_subnode_to_map(struct device *dev, return ret; } -int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *np_config, - struct pinctrl_map **map, unsigned *num_maps) +static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, + unsigned *num_maps) { unsigned reserved_maps; struct device_node *np; @@ -660,7 +662,7 @@ static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev, } #endif -struct pinconf_ops tegra_pinconf_ops = { +static struct pinconf_ops tegra_pinconf_ops = { .pin_config_get = tegra_pinconf_get, .pin_config_set = tegra_pinconf_set, .pin_config_group_get = tegra_pinconf_group_get, diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c index 309f5b9a70ec74d4b5e1cca07b6e8e31836f53fa..b84de03ed54d418e7d7b00176381899e02110b48 100644 --- a/drivers/pinctrl/pinctrl-u300.c +++ b/drivers/pinctrl/pinctrl-u300.c @@ -663,8 +663,6 @@ static const struct pinctrl_pin_desc u300_pads[] = { struct u300_pmx { struct device *dev; struct pinctrl_dev *pctl; - u32 phybase; - u32 physize; void __iomem *virtbase; }; @@ -1013,52 +1011,11 @@ static struct pinmux_ops u300_pmx_ops = { .disable = u300_pmx_disable, }; -/* - * GPIO ranges handled by the application-side COH901XXX GPIO controller - * Very many pins can be converted into GPIO pins, but we only list those - * that are useful in practice to cut down on tables. - */ -#define U300_GPIO_RANGE(a, b, c) { .name = "COH901XXX", .id = a, .base= a, \ - .pin_base = b, .npins = c } - -static struct pinctrl_gpio_range u300_gpio_ranges[] = { - U300_GPIO_RANGE(10, 426, 1), - U300_GPIO_RANGE(11, 180, 1), - U300_GPIO_RANGE(12, 165, 1), /* MS/MMC card insertion */ - U300_GPIO_RANGE(13, 179, 1), - U300_GPIO_RANGE(14, 178, 1), - U300_GPIO_RANGE(16, 194, 1), - U300_GPIO_RANGE(17, 193, 1), - U300_GPIO_RANGE(18, 192, 1), - U300_GPIO_RANGE(19, 191, 1), - U300_GPIO_RANGE(20, 186, 1), - U300_GPIO_RANGE(21, 185, 1), - U300_GPIO_RANGE(22, 184, 1), - U300_GPIO_RANGE(23, 183, 1), - U300_GPIO_RANGE(24, 182, 1), - U300_GPIO_RANGE(25, 181, 1), -}; - -static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) { - struct pinctrl_gpio_range *range; - - range = &u300_gpio_ranges[i]; - if (pin >= range->pin_base && - pin <= (range->pin_base + range->npins - 1)) - return range; - } - return NULL; -} - -int u300_pin_config_get(struct pinctrl_dev *pctldev, - unsigned pin, - unsigned long *config) +static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config) { - struct pinctrl_gpio_range *range = u300_match_gpio_range(pin); + struct pinctrl_gpio_range *range = + pinctrl_find_gpio_range_from_pin(pctldev, pin); /* We get config for those pins we CAN get it for and that's it */ if (!range) @@ -1069,11 +1026,11 @@ int u300_pin_config_get(struct pinctrl_dev *pctldev, config); } -int u300_pin_config_set(struct pinctrl_dev *pctldev, - unsigned pin, - unsigned long config) +static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long config) { - struct pinctrl_gpio_range *range = u300_match_gpio_range(pin); + struct pinctrl_gpio_range *range = + pinctrl_find_gpio_range_from_pin(pctldev, pin); int ret; if (!range) @@ -1109,9 +1066,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) { struct u300_pmx *upmx; struct resource *res; - struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev); - int ret; - int i; /* Create state holders etc for this driver */ upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL); @@ -1123,32 +1077,15 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENOENT; - upmx->phybase = res->start; - upmx->physize = resource_size(res); - - if (request_mem_region(upmx->phybase, upmx->physize, - DRIVER_NAME) == NULL) { - ret = -ENOMEM; - goto out_no_memregion; - } - upmx->virtbase = ioremap(upmx->phybase, upmx->physize); - if (!upmx->virtbase) { - ret = -ENOMEM; - goto out_no_remap; - } + upmx->virtbase = devm_request_and_ioremap(&pdev->dev, res); + if (!upmx->virtbase) + return -ENOMEM; upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx); if (!upmx->pctl) { dev_err(&pdev->dev, "could not register U300 pinmux driver\n"); - ret = -EINVAL; - goto out_no_pmx; - } - - /* We will handle a range of GPIO pins */ - for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) { - u300_gpio_ranges[i].gc = gpio_chip; - pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]); + return -EINVAL; } platform_set_drvdata(pdev, upmx); @@ -1156,14 +1093,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) dev_info(&pdev->dev, "initialized U300 pin control driver\n"); return 0; - -out_no_pmx: - iounmap(upmx->virtbase); -out_no_remap: - platform_set_drvdata(pdev, NULL); -out_no_memregion: - release_mem_region(upmx->phybase, upmx->physize); - return ret; } static int __devexit u300_pmx_remove(struct platform_device *pdev) @@ -1171,8 +1100,6 @@ static int __devexit u300_pmx_remove(struct platform_device *pdev) struct u300_pmx *upmx = platform_get_drvdata(pdev); pinctrl_unregister(upmx->pctl); - iounmap(upmx->virtbase); - release_mem_region(upmx->phybase, upmx->physize); platform_set_drvdata(pdev, NULL); return 0; diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index b9bcaec6622381ca3461212cad85144b857e1b48..ad90984ec5008a7f39f64e6a498102af13cba583 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c @@ -522,7 +522,7 @@ static int xway_pinconf_set(struct pinctrl_dev *pctldev, return 0; } -struct pinconf_ops xway_pinconf_ops = { +static struct pinconf_ops xway_pinconf_ops = { .pin_config_get = xway_pinconf_get, .pin_config_set = xway_pinconf_set, }; diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 9301a7a95effae0a3f447dcc5aefb8030a9e9a62..1a00658b3ea070f336333160411f1b01bbc8f96e 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, { struct pinctrl_dev *pctldev = setting->pctldev; const struct pinmux_ops *pmxops = pctldev->desc->pmxops; - const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; char const * const *groups; unsigned num_groups; int ret; const char *group; int i; - const unsigned *pins; - unsigned num_pins; if (!pmxops) { dev_err(pctldev->dev, "does not support mux function\n"); @@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, } setting->data.mux.group = ret; - ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins, - &num_pins); - if (ret) { - dev_err(pctldev->dev, - "could not get pins for device %s group selector %d\n", - pinctrl_dev_get_name(pctldev), setting->data.mux.group); - return -ENODEV; - } - - /* Try to allocate all pins in this group, one by one */ - for (i = 0; i < num_pins; i++) { - ret = pin_request(pctldev, pins[i], map->dev_name, NULL); - if (ret) { - dev_err(pctldev->dev, - "could not request pin %d on device %s\n", - pins[i], pinctrl_dev_get_name(pctldev)); - /* On error release all taken pins */ - i--; /* this pin just failed */ - for (; i >= 0; i--) - pin_free(pctldev, pins[i], NULL); - return -ENODEV; - } - } - return 0; } void pinmux_free_setting(struct pinctrl_setting const *setting) { - struct pinctrl_dev *pctldev = setting->pctldev; - const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; - const unsigned *pins; - unsigned num_pins; - int ret; - int i; - - ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, - &pins, &num_pins); - if (ret) { - dev_err(pctldev->dev, - "could not get pins for device %s group selector %d\n", - pinctrl_dev_get_name(pctldev), setting->data.mux.group); - return; - } - - for (i = 0; i < num_pins; i++) - pin_free(pctldev, pins[i], NULL); + /* This function is currently unused */ } int pinmux_enable_setting(struct pinctrl_setting const *setting) @@ -446,6 +402,18 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting) num_pins = 0; } + /* Try to allocate all pins in this group, one by one */ + for (i = 0; i < num_pins; i++) { + ret = pin_request(pctldev, pins[i], setting->dev_name, NULL); + if (ret) { + dev_err(pctldev->dev, + "could not request pin %d on device %s\n", + pins[i], pinctrl_dev_get_name(pctldev)); + goto err_pin_request; + } + } + + /* Now that we have acquired the pins, encode the mux setting */ for (i = 0; i < num_pins; i++) { desc = pin_desc_get(pctldev, pins[i]); if (desc == NULL) { @@ -457,8 +425,26 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting) desc->mux_setting = &(setting->data.mux); } - return ops->enable(pctldev, setting->data.mux.func, - setting->data.mux.group); + ret = ops->enable(pctldev, setting->data.mux.func, + setting->data.mux.group); + + if (ret) + goto err_enable; + + return 0; + +err_enable: + for (i = 0; i < num_pins; i++) { + desc = pin_desc_get(pctldev, pins[i]); + if (desc) + desc->mux_setting = NULL; + } +err_pin_request: + /* On error release all taken pins */ + while (--i >= 0) + pin_free(pctldev, pins[i], NULL); + + return ret; } void pinmux_disable_setting(struct pinctrl_setting const *setting) @@ -482,6 +468,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting) num_pins = 0; } + /* Flag the descs that no setting is active */ for (i = 0; i < num_pins; i++) { desc = pin_desc_get(pctldev, pins[i]); if (desc == NULL) { @@ -493,6 +480,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting) desc->mux_setting = NULL; } + /* And release the pins */ + for (i = 0; i < num_pins; i++) + pin_free(pctldev, pins[i], NULL); + if (ops->disable) ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group); } diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig index 91558791e7666fd0e1ebea3484424b4f9674ea93..04d93e602674c6f2489bba44c4febd4cc5628cf9 100644 --- a/drivers/pinctrl/spear/Kconfig +++ b/drivers/pinctrl/spear/Kconfig @@ -25,20 +25,31 @@ config PINCTRL_SPEAR310 bool "ST Microelectronics SPEAr310 SoC pin controller driver" depends on MACH_SPEAR310 select PINCTRL_SPEAR3XX + select PINCTRL_SPEAR_PLGPIO config PINCTRL_SPEAR320 bool "ST Microelectronics SPEAr320 SoC pin controller driver" depends on MACH_SPEAR320 select PINCTRL_SPEAR3XX + select PINCTRL_SPEAR_PLGPIO config PINCTRL_SPEAR1310 bool "ST Microelectronics SPEAr1310 SoC pin controller driver" depends on MACH_SPEAR1310 select PINCTRL_SPEAR + select PINCTRL_SPEAR_PLGPIO config PINCTRL_SPEAR1340 bool "ST Microelectronics SPEAr1340 SoC pin controller driver" depends on MACH_SPEAR1340 select PINCTRL_SPEAR + select PINCTRL_SPEAR_PLGPIO + +config PINCTRL_SPEAR_PLGPIO + bool "SPEAr SoC PLGPIO Controller" + depends on GPIOLIB && PINCTRL_SPEAR + help + Say yes here to support PLGPIO controller on ST Microelectronics SPEAr + SoCs. endif diff --git a/drivers/pinctrl/spear/Makefile b/drivers/pinctrl/spear/Makefile index b28a7ba224432a656c238d40900af1cabbffc0bb..0e400ebeb8ff6d440a9219fae0efa8644bcc6cb6 100644 --- a/drivers/pinctrl/spear/Makefile +++ b/drivers/pinctrl/spear/Makefile @@ -1,5 +1,6 @@ # SPEAr pinmux support +obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO) += pinctrl-plgpio.o obj-$(CONFIG_PINCTRL_SPEAR) += pinctrl-spear.o obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c new file mode 100644 index 0000000000000000000000000000000000000000..4c045053bbddd1e8a557861f7a73eb51ec64a97e --- /dev/null +++ b/drivers/pinctrl/spear/pinctrl-plgpio.c @@ -0,0 +1,758 @@ +/* + * SPEAr platform PLGPIO driver + * + * Copyright (C) 2012 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_GPIO_PER_REG 32 +#define PIN_OFFSET(pin) (pin % MAX_GPIO_PER_REG) +#define REG_OFFSET(base, reg, pin) (base + reg + (pin / MAX_GPIO_PER_REG) \ + * sizeof(int *)) + +/* + * plgpio pins in all machines are not one to one mapped, bitwise with registers + * bits. These set of macros define register masks for which below functions + * (pin_to_offset and offset_to_pin) are required to be called. + */ +#define PTO_ENB_REG 0x001 +#define PTO_WDATA_REG 0x002 +#define PTO_DIR_REG 0x004 +#define PTO_IE_REG 0x008 +#define PTO_RDATA_REG 0x010 +#define PTO_MIS_REG 0x020 + +struct plgpio_regs { + u32 enb; /* enable register */ + u32 wdata; /* write data register */ + u32 dir; /* direction set register */ + u32 rdata; /* read data register */ + u32 ie; /* interrupt enable register */ + u32 mis; /* mask interrupt status register */ + u32 eit; /* edge interrupt type */ +}; + +/* + * struct plgpio: plgpio driver specific structure + * + * lock: lock for guarding gpio registers + * base: base address of plgpio block + * irq_base: irq number of plgpio0 + * chip: gpio framework specific chip information structure + * p2o: function ptr for pin to offset conversion. This is required only for + * machines where mapping b/w pin and offset is not 1-to-1. + * o2p: function ptr for offset to pin conversion. This is required only for + * machines where mapping b/w pin and offset is not 1-to-1. + * p2o_regs: mask of registers for which p2o and o2p are applicable + * regs: register offsets + * csave_regs: context save registers for standby/sleep/hibernate cases + */ +struct plgpio { + spinlock_t lock; + void __iomem *base; + struct clk *clk; + unsigned irq_base; + struct irq_domain *irq_domain; + struct gpio_chip chip; + int (*p2o)(int pin); /* pin_to_offset */ + int (*o2p)(int offset); /* offset_to_pin */ + u32 p2o_regs; + struct plgpio_regs regs; +#ifdef CONFIG_PM + struct plgpio_regs *csave_regs; +#endif +}; + +/* register manipulation inline functions */ +static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg) +{ + u32 offset = PIN_OFFSET(pin); + void __iomem *reg_off = REG_OFFSET(base, reg, pin); + u32 val = readl_relaxed(reg_off); + + return !!(val & (1 << offset)); +} + +static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg) +{ + u32 offset = PIN_OFFSET(pin); + void __iomem *reg_off = REG_OFFSET(base, reg, pin); + u32 val = readl_relaxed(reg_off); + + writel_relaxed(val | (1 << offset), reg_off); +} + +static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg) +{ + u32 offset = PIN_OFFSET(pin); + void __iomem *reg_off = REG_OFFSET(base, reg, pin); + u32 val = readl_relaxed(reg_off); + + writel_relaxed(val & ~(1 << offset), reg_off); +} + +/* gpio framework specific routines */ +static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct plgpio *plgpio = container_of(chip, struct plgpio, chip); + unsigned long flags; + + /* get correct offset for "offset" pin */ + if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) { + offset = plgpio->p2o(offset); + if (offset == -1) + return -EINVAL; + } + + spin_lock_irqsave(&plgpio->lock, flags); + plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir); + spin_unlock_irqrestore(&plgpio->lock, flags); + + return 0; +} + +static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct plgpio *plgpio = container_of(chip, struct plgpio, chip); + unsigned long flags; + unsigned dir_offset = offset, wdata_offset = offset, tmp; + + /* get correct offset for "offset" pin */ + if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) { + tmp = plgpio->p2o(offset); + if (tmp == -1) + return -EINVAL; + + if (plgpio->p2o_regs & PTO_DIR_REG) + dir_offset = tmp; + if (plgpio->p2o_regs & PTO_WDATA_REG) + wdata_offset = tmp; + } + + spin_lock_irqsave(&plgpio->lock, flags); + if (value) + plgpio_reg_set(plgpio->base, wdata_offset, + plgpio->regs.wdata); + else + plgpio_reg_reset(plgpio->base, wdata_offset, + plgpio->regs.wdata); + + plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir); + spin_unlock_irqrestore(&plgpio->lock, flags); + + return 0; +} + +static int plgpio_get_value(struct gpio_chip *chip, unsigned offset) +{ + struct plgpio *plgpio = container_of(chip, struct plgpio, chip); + + if (offset >= chip->ngpio) + return -EINVAL; + + /* get correct offset for "offset" pin */ + if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) { + offset = plgpio->p2o(offset); + if (offset == -1) + return -EINVAL; + } + + return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata); +} + +static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value) +{ + struct plgpio *plgpio = container_of(chip, struct plgpio, chip); + + if (offset >= chip->ngpio) + return; + + /* get correct offset for "offset" pin */ + if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) { + offset = plgpio->p2o(offset); + if (offset == -1) + return; + } + + if (value) + plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata); + else + plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata); +} + +static int plgpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct plgpio *plgpio = container_of(chip, struct plgpio, chip); + int gpio = chip->base + offset; + unsigned long flags; + int ret = 0; + + if (offset >= chip->ngpio) + return -EINVAL; + + ret = pinctrl_request_gpio(gpio); + if (ret) + return ret; + + if (!IS_ERR(plgpio->clk)) { + ret = clk_enable(plgpio->clk); + if (ret) + goto err0; + } + + if (plgpio->regs.enb == -1) + return 0; + + /* + * put gpio in IN mode before enabling it. This make enabling gpio safe + */ + ret = plgpio_direction_input(chip, offset); + if (ret) + goto err1; + + /* get correct offset for "offset" pin */ + if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) { + offset = plgpio->p2o(offset); + if (offset == -1) { + ret = -EINVAL; + goto err1; + } + } + + spin_lock_irqsave(&plgpio->lock, flags); + plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb); + spin_unlock_irqrestore(&plgpio->lock, flags); + return 0; + +err1: + if (!IS_ERR(plgpio->clk)) + clk_disable(plgpio->clk); +err0: + pinctrl_free_gpio(gpio); + return ret; +} + +static void plgpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct plgpio *plgpio = container_of(chip, struct plgpio, chip); + int gpio = chip->base + offset; + unsigned long flags; + + if (offset >= chip->ngpio) + return; + + if (plgpio->regs.enb == -1) + goto disable_clk; + + /* get correct offset for "offset" pin */ + if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) { + offset = plgpio->p2o(offset); + if (offset == -1) + return; + } + + spin_lock_irqsave(&plgpio->lock, flags); + plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb); + spin_unlock_irqrestore(&plgpio->lock, flags); + +disable_clk: + if (!IS_ERR(plgpio->clk)) + clk_disable(plgpio->clk); + + pinctrl_free_gpio(gpio); +} + +static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct plgpio *plgpio = container_of(chip, struct plgpio, chip); + + if (IS_ERR_VALUE(plgpio->irq_base)) + return -EINVAL; + + return irq_find_mapping(plgpio->irq_domain, offset); +} + +/* PLGPIO IRQ */ +static void plgpio_irq_disable(struct irq_data *d) +{ + struct plgpio *plgpio = irq_data_get_irq_chip_data(d); + int offset = d->irq - plgpio->irq_base; + unsigned long flags; + + /* get correct offset for "offset" pin */ + if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) { + offset = plgpio->p2o(offset); + if (offset == -1) + return; + } + + spin_lock_irqsave(&plgpio->lock, flags); + plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie); + spin_unlock_irqrestore(&plgpio->lock, flags); +} + +static void plgpio_irq_enable(struct irq_data *d) +{ + struct plgpio *plgpio = irq_data_get_irq_chip_data(d); + int offset = d->irq - plgpio->irq_base; + unsigned long flags; + + /* get correct offset for "offset" pin */ + if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) { + offset = plgpio->p2o(offset); + if (offset == -1) + return; + } + + spin_lock_irqsave(&plgpio->lock, flags); + plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie); + spin_unlock_irqrestore(&plgpio->lock, flags); +} + +static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger) +{ + struct plgpio *plgpio = irq_data_get_irq_chip_data(d); + int offset = d->irq - plgpio->irq_base; + void __iomem *reg_off; + unsigned int supported_type = 0, val; + + if (offset >= plgpio->chip.ngpio) + return -EINVAL; + + if (plgpio->regs.eit == -1) + supported_type = IRQ_TYPE_LEVEL_HIGH; + else + supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + + if (!(trigger & supported_type)) + return -EINVAL; + + if (plgpio->regs.eit == -1) + return 0; + + reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset); + val = readl_relaxed(reg_off); + + offset = PIN_OFFSET(offset); + if (trigger & IRQ_TYPE_EDGE_RISING) + writel_relaxed(val | (1 << offset), reg_off); + else + writel_relaxed(val & ~(1 << offset), reg_off); + + return 0; +} + +static struct irq_chip plgpio_irqchip = { + .name = "PLGPIO", + .irq_enable = plgpio_irq_enable, + .irq_disable = plgpio_irq_disable, + .irq_set_type = plgpio_irq_set_type, +}; + +static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc) +{ + struct plgpio *plgpio = irq_get_handler_data(irq); + struct irq_chip *irqchip = irq_desc_get_chip(desc); + int regs_count, count, pin, offset, i = 0; + unsigned long pending; + + count = plgpio->chip.ngpio; + regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG); + + chained_irq_enter(irqchip, desc); + /* check all plgpio MIS registers for a possible interrupt */ + for (; i < regs_count; i++) { + pending = readl_relaxed(plgpio->base + plgpio->regs.mis + + i * sizeof(int *)); + if (!pending) + continue; + + /* clear interrupts */ + writel_relaxed(~pending, plgpio->base + plgpio->regs.mis + + i * sizeof(int *)); + /* + * clear extra bits in last register having gpios < MAX/REG + * ex: Suppose there are max 102 plgpios. then last register + * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits + * so, we must not take other 28 bits into consideration for + * checking interrupt. so clear those bits. + */ + count = count - i * MAX_GPIO_PER_REG; + if (count < MAX_GPIO_PER_REG) + pending &= (1 << count) - 1; + + for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) { + /* get correct pin for "offset" */ + if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) { + pin = plgpio->o2p(offset); + if (pin == -1) + continue; + } else + pin = offset; + + /* get correct irq line number */ + pin = i * MAX_GPIO_PER_REG + pin; + generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin)); + } + } + chained_irq_exit(irqchip, desc); +} + +/* + * pin to offset and offset to pin converter functions + * + * In spear310 there is inconsistency among bit positions in plgpio regiseters, + * for different plgpio pins. For example: for pin 27, bit offset is 23, pin + * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1 + */ +static int spear310_p2o(int pin) +{ + int offset = pin; + + if (pin <= 27) + offset += 4; + else if (pin <= 33) + offset = -1; + else if (pin <= 97) + offset -= 2; + else if (pin <= 101) + offset = 101 - pin; + else + offset = -1; + + return offset; +} + +int spear310_o2p(int offset) +{ + if (offset <= 3) + return 101 - offset; + else if (offset <= 31) + return offset - 4; + else + return offset + 2; +} + +static int __devinit plgpio_probe_dt(struct platform_device *pdev, + struct plgpio *plgpio) +{ + struct device_node *np = pdev->dev.of_node; + int ret = -EINVAL; + u32 val; + + if (of_machine_is_compatible("st,spear310")) { + plgpio->p2o = spear310_p2o; + plgpio->o2p = spear310_o2p; + plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG | + PTO_RDATA_REG | PTO_MIS_REG; + } + + if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) { + plgpio->chip.ngpio = val; + } else { + dev_err(&pdev->dev, "DT: Invalid ngpio field\n"); + goto end; + } + + if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val)) + plgpio->regs.enb = val; + else + plgpio->regs.enb = -1; + + if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) { + plgpio->regs.wdata = val; + } else { + dev_err(&pdev->dev, "DT: Invalid wdata reg\n"); + goto end; + } + + if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) { + plgpio->regs.dir = val; + } else { + dev_err(&pdev->dev, "DT: Invalid dir reg\n"); + goto end; + } + + if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) { + plgpio->regs.ie = val; + } else { + dev_err(&pdev->dev, "DT: Invalid ie reg\n"); + goto end; + } + + if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) { + plgpio->regs.rdata = val; + } else { + dev_err(&pdev->dev, "DT: Invalid rdata reg\n"); + goto end; + } + + if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) { + plgpio->regs.mis = val; + } else { + dev_err(&pdev->dev, "DT: Invalid mis reg\n"); + goto end; + } + + if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val)) + plgpio->regs.eit = val; + else + plgpio->regs.eit = -1; + + return 0; + +end: + return ret; +} +static int __devinit plgpio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct plgpio *plgpio; + struct resource *res; + int ret, irq, i; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n"); + return -EBUSY; + } + + plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL); + if (!plgpio) { + dev_err(&pdev->dev, "memory allocation fail\n"); + return -ENOMEM; + } + + plgpio->base = devm_request_and_ioremap(&pdev->dev, res); + if (!plgpio->base) { + dev_err(&pdev->dev, "request and ioremap fail\n"); + return -ENOMEM; + } + + ret = plgpio_probe_dt(pdev, plgpio); + if (ret) { + dev_err(&pdev->dev, "DT probe failed\n"); + return ret; + } + + plgpio->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(plgpio->clk)) + dev_warn(&pdev->dev, "clk_get() failed, work without it\n"); + +#ifdef CONFIG_PM + plgpio->csave_regs = devm_kzalloc(&pdev->dev, + sizeof(*plgpio->csave_regs) * + DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG), + GFP_KERNEL); + if (!plgpio->csave_regs) { + dev_err(&pdev->dev, "csave registers memory allocation fail\n"); + return -ENOMEM; + } +#endif + + platform_set_drvdata(pdev, plgpio); + spin_lock_init(&plgpio->lock); + + plgpio->irq_base = -1; + plgpio->chip.base = -1; + plgpio->chip.request = plgpio_request; + plgpio->chip.free = plgpio_free; + plgpio->chip.direction_input = plgpio_direction_input; + plgpio->chip.direction_output = plgpio_direction_output; + plgpio->chip.get = plgpio_get_value; + plgpio->chip.set = plgpio_set_value; + plgpio->chip.to_irq = plgpio_to_irq; + plgpio->chip.label = dev_name(&pdev->dev); + plgpio->chip.dev = &pdev->dev; + plgpio->chip.owner = THIS_MODULE; + + if (!IS_ERR(plgpio->clk)) { + ret = clk_prepare(plgpio->clk); + if (ret) { + dev_err(&pdev->dev, "clk prepare failed\n"); + return ret; + } + } + + ret = gpiochip_add(&plgpio->chip); + if (ret) { + dev_err(&pdev->dev, "unable to add gpio chip\n"); + goto unprepare_clk; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_info(&pdev->dev, "irqs not supported\n"); + return 0; + } + + plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0); + if (IS_ERR_VALUE(plgpio->irq_base)) { + /* we would not support irq for gpio */ + dev_warn(&pdev->dev, "couldn't allocate irq base\n"); + return 0; + } + + plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio, + plgpio->irq_base, 0, &irq_domain_simple_ops, NULL); + if (WARN_ON(!plgpio->irq_domain)) { + dev_err(&pdev->dev, "irq domain init failed\n"); + irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio); + ret = -ENXIO; + goto remove_gpiochip; + } + + irq_set_chained_handler(irq, plgpio_irq_handler); + for (i = 0; i < plgpio->chip.ngpio; i++) { + irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip, + handle_simple_irq); + set_irq_flags(i + plgpio->irq_base, IRQF_VALID); + irq_set_chip_data(i + plgpio->irq_base, plgpio); + } + + irq_set_handler_data(irq, plgpio); + dev_info(&pdev->dev, "PLGPIO registered with IRQs\n"); + + return 0; + +remove_gpiochip: + dev_info(&pdev->dev, "Remove gpiochip\n"); + if (gpiochip_remove(&plgpio->chip)) + dev_err(&pdev->dev, "unable to remove gpiochip\n"); +unprepare_clk: + if (!IS_ERR(plgpio->clk)) + clk_unprepare(plgpio->clk); + + return ret; +} + +#ifdef CONFIG_PM +static int plgpio_suspend(struct device *dev) +{ + struct plgpio *plgpio = dev_get_drvdata(dev); + int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG); + void __iomem *off; + + for (i = 0; i < reg_count; i++) { + off = plgpio->base + i * sizeof(int *); + + if (plgpio->regs.enb != -1) + plgpio->csave_regs[i].enb = + readl_relaxed(plgpio->regs.enb + off); + if (plgpio->regs.eit != -1) + plgpio->csave_regs[i].eit = + readl_relaxed(plgpio->regs.eit + off); + plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata + + off); + plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir + + off); + plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off); + } + + return 0; +} + +/* + * This is used to correct the values in end registers. End registers contain + * extra bits that might be used for other purpose in platform. So, we shouldn't + * overwrite these bits. This macro, reads given register again, preserves other + * bit values (non-plgpio bits), and retain captured value (plgpio bits). + */ +#define plgpio_prepare_reg(__reg, _off, _mask, _tmp) \ +{ \ + _tmp = readl_relaxed(plgpio->regs.__reg + _off); \ + _tmp &= ~_mask; \ + plgpio->csave_regs[i].__reg = \ + _tmp | (plgpio->csave_regs[i].__reg & _mask); \ +} + +static int plgpio_resume(struct device *dev) +{ + struct plgpio *plgpio = dev_get_drvdata(dev); + int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG); + void __iomem *off; + u32 mask, tmp; + + for (i = 0; i < reg_count; i++) { + off = plgpio->base + i * sizeof(int *); + + if (i == reg_count - 1) { + mask = (1 << (plgpio->chip.ngpio - i * + MAX_GPIO_PER_REG)) - 1; + + if (plgpio->regs.enb != -1) + plgpio_prepare_reg(enb, off, mask, tmp); + + if (plgpio->regs.eit != -1) + plgpio_prepare_reg(eit, off, mask, tmp); + + plgpio_prepare_reg(wdata, off, mask, tmp); + plgpio_prepare_reg(dir, off, mask, tmp); + plgpio_prepare_reg(ie, off, mask, tmp); + } + + writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata + + off); + writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir + + off); + + if (plgpio->regs.eit != -1) + writel_relaxed(plgpio->csave_regs[i].eit, + plgpio->regs.eit + off); + + writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off); + + if (plgpio->regs.enb != -1) + writel_relaxed(plgpio->csave_regs[i].enb, + plgpio->regs.enb + off); + } + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume); + +static const struct of_device_id plgpio_of_match[] = { + { .compatible = "st,spear-plgpio" }, + {} +}; +MODULE_DEVICE_TABLE(of, plgpio_of_match); + +static struct platform_driver plgpio_driver = { + .probe = plgpio_probe, + .driver = { + .owner = THIS_MODULE, + .name = "spear-plgpio", + .pm = &plgpio_dev_pm_ops, + .of_match_table = of_match_ptr(plgpio_of_match), + }, +}; + +static int __init plgpio_init(void) +{ + return platform_driver_register(&plgpio_driver); +} +subsys_initcall(plgpio_init); + +MODULE_AUTHOR("Viresh Kumar "); +MODULE_DESCRIPTION("ST Microlectronics SPEAr PLGPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index b1fd6ee33c6ceed614e3a5ccf1cb096049069710..bf78eb7f85c4ebb58e2964562b57a102bb06bf0f 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -14,10 +14,10 @@ */ #include -#include #include #include #include +#include #include #include #include @@ -28,14 +28,26 @@ #define DRIVER_NAME "spear-pinmux" -static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg) +static void muxregs_endisable(struct spear_pmx *pmx, + struct spear_muxreg *muxregs, u8 count, bool enable) { - return readl_relaxed(pmx->vbase + reg); -} + struct spear_muxreg *muxreg; + u32 val, temp, j; -static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg) -{ - writel_relaxed(val, pmx->vbase + reg); + for (j = 0; j < count; j++) { + muxreg = &muxregs[j]; + + val = pmx_readl(pmx, muxreg->reg); + val &= ~muxreg->mask; + + if (enable) + temp = muxreg->val; + else + temp = ~muxreg->val; + + val |= muxreg->mask & temp; + pmx_writel(pmx, val, muxreg->reg); + } } static int set_mode(struct spear_pmx *pmx, int mode) @@ -70,6 +82,17 @@ static int set_mode(struct spear_pmx *pmx, int mode) return 0; } +void __devinit +pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup, + unsigned count, u16 reg) +{ + int i, j; + + for (i = 0; i < count; i++) + for (j = 0; j < gpio_pingroup[i].nmuxregs; j++) + gpio_pingroup[i].muxregs[j].reg = reg; +} + void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg) { struct spear_pingroup *pgroup; @@ -121,9 +144,10 @@ static void spear_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, " " DRIVER_NAME); } -int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *np_config, - struct pinctrl_map **map, unsigned *num_maps) +static int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, + unsigned *num_maps) { struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct device_node *np; @@ -168,8 +192,9 @@ int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, return 0; } -void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, - struct pinctrl_map *map, unsigned num_maps) +static void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, + unsigned num_maps) { kfree(map); } @@ -216,9 +241,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev, struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); const struct spear_pingroup *pgroup; const struct spear_modemux *modemux; - struct spear_muxreg *muxreg; - u32 val, temp; - int i, j; + int i; bool found = false; pgroup = pmx->machdata->groups[group]; @@ -233,20 +256,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev, } found = true; - for (j = 0; j < modemux->nmuxregs; j++) { - muxreg = &modemux->muxregs[j]; - - val = pmx_readl(pmx, muxreg->reg); - val &= ~muxreg->mask; - - if (enable) - temp = muxreg->val; - else - temp = ~muxreg->val; - - val |= muxreg->mask & temp; - pmx_writel(pmx, val, muxreg->reg); - } + muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs, + enable); } if (!found) { @@ -270,12 +281,74 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev, spear_pinctrl_endisable(pctldev, function, group, false); } +/* gpio with pinmux */ +static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx, + unsigned pin) +{ + struct spear_gpio_pingroup *gpio_pingroup; + int i, j; + + if (!pmx->machdata->gpio_pingroups) + return NULL; + + for (i = 0; i < pmx->machdata->ngpio_pingroups; i++) { + gpio_pingroup = &pmx->machdata->gpio_pingroups[i]; + + for (j = 0; j < gpio_pingroup->npins; j++) { + if (gpio_pingroup->pins[j] == pin) + return gpio_pingroup; + } + } + + return NULL; +} + +static int gpio_request_endisable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned offset, bool enable) +{ + struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + struct spear_pinctrl_machdata *machdata = pmx->machdata; + struct spear_gpio_pingroup *gpio_pingroup; + + /* + * Some SoC have configuration options applicable to group of pins, + * rather than a single pin. + */ + gpio_pingroup = get_gpio_pingroup(pmx, offset); + if (gpio_pingroup) + muxregs_endisable(pmx, gpio_pingroup->muxregs, + gpio_pingroup->nmuxregs, enable); + + /* + * SoC may need some extra configurations, or configurations for single + * pin + */ + if (machdata->gpio_request_endisable) + machdata->gpio_request_endisable(pmx, offset, enable); + + return 0; +} + +static int gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned offset) +{ + return gpio_request_endisable(pctldev, range, offset, true); +} + +static void gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned offset) +{ + gpio_request_endisable(pctldev, range, offset, false); +} + static struct pinmux_ops spear_pinmux_ops = { .get_functions_count = spear_pinctrl_get_funcs_count, .get_function_name = spear_pinctrl_get_func_name, .get_function_groups = spear_pinctrl_get_func_groups, .enable = spear_pinctrl_enable, .disable = spear_pinctrl_disable, + .gpio_request_enable = gpio_request_enable, + .gpio_disable_free = gpio_disable_free, }; static struct pinctrl_desc spear_pinctrl_desc = { diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h index d950eb78d939679af768c754f45adea5ea2a7f23..b06332719b2c8fb59d8dc1b5311a46a56d27b7dd 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.h +++ b/drivers/pinctrl/spear/pinctrl-spear.h @@ -12,11 +12,14 @@ #ifndef __PINMUX_SPEAR_H__ #define __PINMUX_SPEAR_H__ +#include +#include #include #include struct platform_device; struct device; +struct spear_pmx; /** * struct spear_pmx_mode - SPEAr pmx mode @@ -46,6 +49,44 @@ struct spear_muxreg { u32 val; }; +struct spear_gpio_pingroup { + const unsigned *pins; + unsigned npins; + struct spear_muxreg *muxregs; + u8 nmuxregs; +}; + +/* ste: set to enable */ +#define DEFINE_MUXREG(__pins, __muxreg, __mask, __ste) \ +static struct spear_muxreg __pins##_muxregs[] = { \ + { \ + .reg = __muxreg, \ + .mask = __mask, \ + .val = __ste ? __mask : 0, \ + }, \ +} + +#define DEFINE_2_MUXREG(__pins, __muxreg1, __muxreg2, __mask, __ste1, __ste2) \ +static struct spear_muxreg __pins##_muxregs[] = { \ + { \ + .reg = __muxreg1, \ + .mask = __mask, \ + .val = __ste1 ? __mask : 0, \ + }, { \ + .reg = __muxreg2, \ + .mask = __mask, \ + .val = __ste2 ? __mask : 0, \ + }, \ +} + +#define GPIO_PINGROUP(__pins) \ + { \ + .pins = __pins, \ + .npins = ARRAY_SIZE(__pins), \ + .muxregs = __pins##_muxregs, \ + .nmuxregs = ARRAY_SIZE(__pins##_muxregs), \ + } + /** * struct spear_modemux - SPEAr mode mux configuration * @modes: mode ids supported by this group of muxregs @@ -100,6 +141,8 @@ struct spear_function { * @nfunctions: The numbmer of entries in @functions. * @groups: An array describing all pin groups the pin SoC supports. * @ngroups: The numbmer of entries in @groups. + * @gpio_pingroups: gpio pingroups + * @ngpio_pingroups: gpio pingroups count * * @modes_supported: Does SoC support modes * @mode: mode configured from probe @@ -113,6 +156,10 @@ struct spear_pinctrl_machdata { unsigned nfunctions; struct spear_pingroup **groups; unsigned ngroups; + struct spear_gpio_pingroup *gpio_pingroups; + void (*gpio_request_endisable)(struct spear_pmx *pmx, int offset, + bool enable); + unsigned ngpio_pingroups; bool modes_supported; u16 mode; @@ -135,7 +182,20 @@ struct spear_pmx { }; /* exported routines */ +static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg) +{ + return readl_relaxed(pmx->vbase + reg); +} + +static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg) +{ + writel_relaxed(val, pmx->vbase + reg); +} + void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg); +void __devinit +pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup, + unsigned count, u16 reg); int __devinit spear_pinctrl_probe(struct platform_device *pdev, struct spear_pinctrl_machdata *machdata); int __devexit spear_pinctrl_remove(struct platform_device *pdev); diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c index 0436fc7895d6226a8c0cd4943fad2201b03ad4b5..30134f72745567e3a769ad9d6c75d1e0dbc3e136 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1310.c +++ b/drivers/pinctrl/spear/pinctrl-spear1310.c @@ -2418,6 +2418,268 @@ static struct spear_function *spear1310_functions[] = { &gpt64_function, }; +static const unsigned pin18[] = { 18, }; +static const unsigned pin19[] = { 19, }; +static const unsigned pin20[] = { 20, }; +static const unsigned pin21[] = { 21, }; +static const unsigned pin22[] = { 22, }; +static const unsigned pin23[] = { 23, }; +static const unsigned pin54[] = { 54, }; +static const unsigned pin55[] = { 55, }; +static const unsigned pin56[] = { 56, }; +static const unsigned pin57[] = { 57, }; +static const unsigned pin58[] = { 58, }; +static const unsigned pin59[] = { 59, }; +static const unsigned pin60[] = { 60, }; +static const unsigned pin61[] = { 61, }; +static const unsigned pin62[] = { 62, }; +static const unsigned pin63[] = { 63, }; +static const unsigned pin143[] = { 143, }; +static const unsigned pin144[] = { 144, }; +static const unsigned pin145[] = { 145, }; +static const unsigned pin146[] = { 146, }; +static const unsigned pin147[] = { 147, }; +static const unsigned pin148[] = { 148, }; +static const unsigned pin149[] = { 149, }; +static const unsigned pin150[] = { 150, }; +static const unsigned pin151[] = { 151, }; +static const unsigned pin152[] = { 152, }; +static const unsigned pin205[] = { 205, }; +static const unsigned pin206[] = { 206, }; +static const unsigned pin211[] = { 211, }; +static const unsigned pin212[] = { 212, }; +static const unsigned pin213[] = { 213, }; +static const unsigned pin214[] = { 214, }; +static const unsigned pin215[] = { 215, }; +static const unsigned pin216[] = { 216, }; +static const unsigned pin217[] = { 217, }; +static const unsigned pin218[] = { 218, }; +static const unsigned pin219[] = { 219, }; +static const unsigned pin220[] = { 220, }; +static const unsigned pin221[] = { 221, }; +static const unsigned pin222[] = { 222, }; +static const unsigned pin223[] = { 223, }; +static const unsigned pin224[] = { 224, }; +static const unsigned pin225[] = { 225, }; +static const unsigned pin226[] = { 226, }; +static const unsigned pin227[] = { 227, }; +static const unsigned pin228[] = { 228, }; +static const unsigned pin229[] = { 229, }; +static const unsigned pin230[] = { 230, }; +static const unsigned pin231[] = { 231, }; +static const unsigned pin232[] = { 232, }; +static const unsigned pin233[] = { 233, }; +static const unsigned pin234[] = { 234, }; +static const unsigned pin235[] = { 235, }; +static const unsigned pin236[] = { 236, }; +static const unsigned pin237[] = { 237, }; +static const unsigned pin238[] = { 238, }; +static const unsigned pin239[] = { 239, }; +static const unsigned pin240[] = { 240, }; +static const unsigned pin241[] = { 241, }; +static const unsigned pin242[] = { 242, }; +static const unsigned pin243[] = { 243, }; +static const unsigned pin244[] = { 244, }; +static const unsigned pin245[] = { 245, }; + +static const unsigned pin_grp0[] = { 173, 174, }; +static const unsigned pin_grp1[] = { 175, 185, 188, 197, 198, }; +static const unsigned pin_grp2[] = { 176, 177, 178, 179, 184, 186, 187, 189, + 190, 191, 192, }; +static const unsigned pin_grp3[] = { 180, 181, 182, 183, 193, 194, 195, 196, }; +static const unsigned pin_grp4[] = { 199, 200, }; +static const unsigned pin_grp5[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, }; +static const unsigned pin_grp6[] = { 86, 87, 88, 89, 90, 91, 92, 93, }; +static const unsigned pin_grp7[] = { 98, 99, }; +static const unsigned pin_grp8[] = { 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, }; + +/* Define muxreg arrays */ +DEFINE_2_MUXREG(i2c0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2C0_MASK, 0, 1); +DEFINE_2_MUXREG(ssp0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SSP0_MASK, 0, 1); +DEFINE_2_MUXREG(ssp0_cs0_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS0_MASK, 0, 1); +DEFINE_2_MUXREG(ssp0_cs1_2_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS1_2_MASK, 0, 1); +DEFINE_2_MUXREG(i2s0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2S0_MASK, 0, 1); +DEFINE_2_MUXREG(i2s1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_I2S1_MASK, 0, 1); +DEFINE_2_MUXREG(clcd_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_CLCD1_MASK, 0, 1); +DEFINE_2_MUXREG(clcd_high_res_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_CLCD2_MASK, 0, 1); +DEFINE_2_MUXREG(pin18, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO15_MASK, 0, 1); +DEFINE_2_MUXREG(pin19, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO14_MASK, 0, 1); +DEFINE_2_MUXREG(pin20, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO13_MASK, 0, 1); +DEFINE_2_MUXREG(pin21, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO12_MASK, 0, 1); +DEFINE_2_MUXREG(pin22, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO11_MASK, 0, 1); +DEFINE_2_MUXREG(pin23, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO10_MASK, 0, 1); +DEFINE_2_MUXREG(pin143, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO00_MASK, 0, 1); +DEFINE_2_MUXREG(pin144, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO01_MASK, 0, 1); +DEFINE_2_MUXREG(pin145, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO02_MASK, 0, 1); +DEFINE_2_MUXREG(pin146, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO03_MASK, 0, 1); +DEFINE_2_MUXREG(pin147, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO04_MASK, 0, 1); +DEFINE_2_MUXREG(pin148, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO05_MASK, 0, 1); +DEFINE_2_MUXREG(pin149, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO06_MASK, 0, 1); +DEFINE_2_MUXREG(pin150, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO07_MASK, 0, 1); +DEFINE_2_MUXREG(pin151, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO08_MASK, 0, 1); +DEFINE_2_MUXREG(pin152, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO09_MASK, 0, 1); +DEFINE_2_MUXREG(smi_2_chips_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SMI_MASK, 0, 1); +DEFINE_2_MUXREG(pin54, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS3_MASK, 0, 1); +DEFINE_2_MUXREG(pin55, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS2_MASK, 0, 1); +DEFINE_2_MUXREG(pin56, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFRSTPWDWN3_MASK, 0, 1); +DEFINE_2_MUXREG(pin57, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN2_MASK, 0, 1); +DEFINE_2_MUXREG(pin58, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN1_MASK, 0, 1); +DEFINE_2_MUXREG(pin59, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN0_MASK, 0, 1); +DEFINE_2_MUXREG(pin60, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFWPRT3_MASK, 0, 1); +DEFINE_2_MUXREG(pin61, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFCE3_MASK, 0, 1); +DEFINE_2_MUXREG(pin62, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD25_MASK, 0, 1); +DEFINE_2_MUXREG(pin63, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD24_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp0, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICLK_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp1, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp2, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_RXCLK_RDV_TXEN_D03_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp3, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIID47_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp4, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MDC_MDIO_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp5, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD23_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp6, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MCI_DATA8_15_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp7, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFCE2_MASK, 0, 1); +DEFINE_2_MUXREG(pin_grp8, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND8_MASK, 0, 1); +DEFINE_2_MUXREG(nand_16bit_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND16BIT_1_MASK, 0, 1); +DEFINE_2_MUXREG(pin205, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL1_MASK | PMX_NFCE1_MASK, 0, 1); +DEFINE_2_MUXREG(pin206, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL0_MASK | PMX_NFCE2_MASK, 0, 1); +DEFINE_2_MUXREG(pin211, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW1_MASK | PMX_NFWPRT1_MASK, 0, 1); +DEFINE_2_MUXREG(pin212, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW0_MASK | PMX_NFWPRT2_MASK, 0, 1); +DEFINE_2_MUXREG(pin213, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA0_MASK, 0, 1); +DEFINE_2_MUXREG(pin214, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA1_MASK, 0, 1); +DEFINE_2_MUXREG(pin215, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA2_MASK, 0, 1); +DEFINE_2_MUXREG(pin216, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA3_MASK, 0, 1); +DEFINE_2_MUXREG(pin217, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA4_MASK, 0, 1); +DEFINE_2_MUXREG(pin218, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA5_MASK, 0, 1); +DEFINE_2_MUXREG(pin219, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA6_MASK, 0, 1); +DEFINE_2_MUXREG(pin220, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA7_MASK, 0, 1); +DEFINE_2_MUXREG(pin221, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA1SD_MASK, 0, 1); +DEFINE_2_MUXREG(pin222, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA2SD_MASK, 0, 1); +DEFINE_2_MUXREG(pin223, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA3SD_MASK, 0, 1); +DEFINE_2_MUXREG(pin224, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR0ALE_MASK, 0, 1); +DEFINE_2_MUXREG(pin225, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR1CLECLK_MASK, 0, 1); +DEFINE_2_MUXREG(pin226, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR2_MASK, 0, 1); +DEFINE_2_MUXREG(pin227, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICECF_MASK, 0, 1); +DEFINE_2_MUXREG(pin228, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICEXD_MASK, 0, 1); +DEFINE_2_MUXREG(pin229, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICESDMMC_MASK, 0, 1); +DEFINE_2_MUXREG(pin230, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF1_MASK, 0, 1); +DEFINE_2_MUXREG(pin231, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF2_MASK, 0, 1); +DEFINE_2_MUXREG(pin232, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDXD_MASK, 0, 1); +DEFINE_2_MUXREG(pin233, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDSDMMC_MASK, 0, 1); +DEFINE_2_MUXREG(pin234, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATADIR_MASK, 0, 1); +DEFINE_2_MUXREG(pin235, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMARQWP_MASK, 0, 1); +DEFINE_2_MUXREG(pin236, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDRE_MASK, 0, 1); +DEFINE_2_MUXREG(pin237, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIOWRWE_MASK, 0, 1); +DEFINE_2_MUXREG(pin238, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIRESETCF_MASK, 0, 1); +DEFINE_2_MUXREG(pin239, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS0CE_MASK, 0, 1); +DEFINE_2_MUXREG(pin240, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICFINTR_MASK, 0, 1); +DEFINE_2_MUXREG(pin241, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDY_MASK, 0, 1); +DEFINE_2_MUXREG(pin242, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS1_MASK, 0, 1); +DEFINE_2_MUXREG(pin243, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMAACK_MASK, 0, 1); +DEFINE_2_MUXREG(pin244, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCISDCMD_MASK, 0, 1); +DEFINE_2_MUXREG(pin245, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCILEDS_MASK, 0, 1); +DEFINE_2_MUXREG(keyboard_rowcol6_8_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROWCOL68_MASK, 0, 1); +DEFINE_2_MUXREG(uart0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_UART0_MASK, 0, 1); +DEFINE_2_MUXREG(uart0_modem_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_UART0_MODEM_MASK, 0, 1); +DEFINE_2_MUXREG(gpt0_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR0_MASK, 0, 1); +DEFINE_2_MUXREG(gpt0_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR1_MASK, 0, 1); +DEFINE_2_MUXREG(gpt1_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR0_MASK, 0, 1); +DEFINE_2_MUXREG(gpt1_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR1_MASK, 0, 1); +DEFINE_2_MUXREG(touch_xy_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_TOUCH_XY_MASK, 0, 1); + +static struct spear_gpio_pingroup spear1310_gpio_pingroup[] = { + GPIO_PINGROUP(i2c0_pins), + GPIO_PINGROUP(ssp0_pins), + GPIO_PINGROUP(ssp0_cs0_pins), + GPIO_PINGROUP(ssp0_cs1_2_pins), + GPIO_PINGROUP(i2s0_pins), + GPIO_PINGROUP(i2s1_pins), + GPIO_PINGROUP(clcd_pins), + GPIO_PINGROUP(clcd_high_res_pins), + GPIO_PINGROUP(pin18), + GPIO_PINGROUP(pin19), + GPIO_PINGROUP(pin20), + GPIO_PINGROUP(pin21), + GPIO_PINGROUP(pin22), + GPIO_PINGROUP(pin23), + GPIO_PINGROUP(pin143), + GPIO_PINGROUP(pin144), + GPIO_PINGROUP(pin145), + GPIO_PINGROUP(pin146), + GPIO_PINGROUP(pin147), + GPIO_PINGROUP(pin148), + GPIO_PINGROUP(pin149), + GPIO_PINGROUP(pin150), + GPIO_PINGROUP(pin151), + GPIO_PINGROUP(pin152), + GPIO_PINGROUP(smi_2_chips_pins), + GPIO_PINGROUP(pin54), + GPIO_PINGROUP(pin55), + GPIO_PINGROUP(pin56), + GPIO_PINGROUP(pin57), + GPIO_PINGROUP(pin58), + GPIO_PINGROUP(pin59), + GPIO_PINGROUP(pin60), + GPIO_PINGROUP(pin61), + GPIO_PINGROUP(pin62), + GPIO_PINGROUP(pin63), + GPIO_PINGROUP(pin_grp0), + GPIO_PINGROUP(pin_grp1), + GPIO_PINGROUP(pin_grp2), + GPIO_PINGROUP(pin_grp3), + GPIO_PINGROUP(pin_grp4), + GPIO_PINGROUP(pin_grp5), + GPIO_PINGROUP(pin_grp6), + GPIO_PINGROUP(pin_grp7), + GPIO_PINGROUP(pin_grp8), + GPIO_PINGROUP(nand_16bit_pins), + GPIO_PINGROUP(pin205), + GPIO_PINGROUP(pin206), + GPIO_PINGROUP(pin211), + GPIO_PINGROUP(pin212), + GPIO_PINGROUP(pin213), + GPIO_PINGROUP(pin214), + GPIO_PINGROUP(pin215), + GPIO_PINGROUP(pin216), + GPIO_PINGROUP(pin217), + GPIO_PINGROUP(pin218), + GPIO_PINGROUP(pin219), + GPIO_PINGROUP(pin220), + GPIO_PINGROUP(pin221), + GPIO_PINGROUP(pin222), + GPIO_PINGROUP(pin223), + GPIO_PINGROUP(pin224), + GPIO_PINGROUP(pin225), + GPIO_PINGROUP(pin226), + GPIO_PINGROUP(pin227), + GPIO_PINGROUP(pin228), + GPIO_PINGROUP(pin229), + GPIO_PINGROUP(pin230), + GPIO_PINGROUP(pin231), + GPIO_PINGROUP(pin232), + GPIO_PINGROUP(pin233), + GPIO_PINGROUP(pin234), + GPIO_PINGROUP(pin235), + GPIO_PINGROUP(pin236), + GPIO_PINGROUP(pin237), + GPIO_PINGROUP(pin238), + GPIO_PINGROUP(pin239), + GPIO_PINGROUP(pin240), + GPIO_PINGROUP(pin241), + GPIO_PINGROUP(pin242), + GPIO_PINGROUP(pin243), + GPIO_PINGROUP(pin244), + GPIO_PINGROUP(pin245), + GPIO_PINGROUP(keyboard_rowcol6_8_pins), + GPIO_PINGROUP(uart0_pins), + GPIO_PINGROUP(uart0_modem_pins), + GPIO_PINGROUP(gpt0_tmr0_pins), + GPIO_PINGROUP(gpt0_tmr1_pins), + GPIO_PINGROUP(gpt1_tmr0_pins), + GPIO_PINGROUP(gpt1_tmr1_pins), + GPIO_PINGROUP(touch_xy_pins), +}; + static struct spear_pinctrl_machdata spear1310_machdata = { .pins = spear1310_pins, .npins = ARRAY_SIZE(spear1310_pins), @@ -2425,6 +2687,8 @@ static struct spear_pinctrl_machdata spear1310_machdata = { .ngroups = ARRAY_SIZE(spear1310_pingroups), .functions = spear1310_functions, .nfunctions = ARRAY_SIZE(spear1310_functions), + .gpio_pingroups = spear1310_gpio_pingroup, + .ngpio_pingroups = ARRAY_SIZE(spear1310_gpio_pingroup), .modes_supported = false, }; diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c index 0606b8cf3f2c10923014917d190d3f5ef73cd0aa..0b4af0e5cdc15428909ed4780b80938f50c04df3 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1340.c +++ b/drivers/pinctrl/spear/pinctrl-spear1340.c @@ -1971,6 +1971,32 @@ static struct spear_function *spear1340_functions[] = { &sata_function, }; +static void gpio_request_endisable(struct spear_pmx *pmx, int pin, + bool enable) +{ + unsigned int regoffset, regindex, bitoffset; + unsigned int val; + + /* pin++ as gpio configuration starts from 2nd bit of base register */ + pin++; + + regindex = pin / 32; + bitoffset = pin % 32; + + if (regindex <= 3) + regoffset = PAD_FUNCTION_EN_1 + regindex * sizeof(int *); + else + regoffset = PAD_FUNCTION_EN_5 + (regindex - 4) * sizeof(int *); + + val = pmx_readl(pmx, regoffset); + if (enable) + val &= ~(0x1 << bitoffset); + else + val |= 0x1 << bitoffset; + + pmx_writel(pmx, val, regoffset); +} + static struct spear_pinctrl_machdata spear1340_machdata = { .pins = spear1340_pins, .npins = ARRAY_SIZE(spear1340_pins), @@ -1978,6 +2004,7 @@ static struct spear_pinctrl_machdata spear1340_machdata = { .ngroups = ARRAY_SIZE(spear1340_pingroups), .functions = spear1340_functions, .nfunctions = ARRAY_SIZE(spear1340_functions), + .gpio_request_endisable = gpio_request_endisable, .modes_supported = false, }; diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c index 4dfc2849b1728d33a913958fbe0bda5fc67c0001..9a491007f42de296c06f73a92f856b35fc6dc410 100644 --- a/drivers/pinctrl/spear/pinctrl-spear300.c +++ b/drivers/pinctrl/spear/pinctrl-spear300.c @@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev) spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups); spear3xx_machdata.functions = spear300_functions; spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions); + spear3xx_machdata.gpio_pingroups = NULL; + spear3xx_machdata.ngpio_pingroups = 0; spear3xx_machdata.modes_supported = true; spear3xx_machdata.pmx_modes = spear300_pmx_modes; diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c index 96883693fb7eeb9d2b5b403ce0a17b10a2bcc94e..4d5dfe9c760acfafd69664453d21398ff14552e8 100644 --- a/drivers/pinctrl/spear/pinctrl-spear310.c +++ b/drivers/pinctrl/spear/pinctrl-spear310.c @@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev) spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions); pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG); + pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups, + spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG); spear3xx_machdata.modes_supported = false; diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c index ca47b0e50780c52b884c7155349ad107fd098a93..c996e26e3b6c3e20a5bdce7335b37e02bace0844 100644 --- a/drivers/pinctrl/spear/pinctrl-spear320.c +++ b/drivers/pinctrl/spear/pinctrl-spear320.c @@ -3431,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev) spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes); pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG); + pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups, + spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG); ret = spear_pinctrl_probe(pdev, &spear3xx_machdata); if (ret) diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.c b/drivers/pinctrl/spear/pinctrl-spear3xx.c index 0242378f7cb86c677a055d9c2c6bcc93797efad7..12ee21af766b1ffafedc935e4bebbdb00065baf6 100644 --- a/drivers/pinctrl/spear/pinctrl-spear3xx.c +++ b/drivers/pinctrl/spear/pinctrl-spear3xx.c @@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = { .ngroups = ARRAY_SIZE(timer_2_3_grps), }; +/* Define muxreg arrays */ +DEFINE_MUXREG(firda_pins, 0, PMX_FIRDA_MASK, 0); +DEFINE_MUXREG(i2c_pins, 0, PMX_I2C_MASK, 0); +DEFINE_MUXREG(ssp_cs_pins, 0, PMX_SSP_CS_MASK, 0); +DEFINE_MUXREG(ssp_pins, 0, PMX_SSP_MASK, 0); +DEFINE_MUXREG(mii_pins, 0, PMX_MII_MASK, 0); +DEFINE_MUXREG(gpio0_pin0_pins, 0, PMX_GPIO_PIN0_MASK, 0); +DEFINE_MUXREG(gpio0_pin1_pins, 0, PMX_GPIO_PIN1_MASK, 0); +DEFINE_MUXREG(gpio0_pin2_pins, 0, PMX_GPIO_PIN2_MASK, 0); +DEFINE_MUXREG(gpio0_pin3_pins, 0, PMX_GPIO_PIN3_MASK, 0); +DEFINE_MUXREG(gpio0_pin4_pins, 0, PMX_GPIO_PIN4_MASK, 0); +DEFINE_MUXREG(gpio0_pin5_pins, 0, PMX_GPIO_PIN5_MASK, 0); +DEFINE_MUXREG(uart0_ext_pins, 0, PMX_UART0_MODEM_MASK, 0); +DEFINE_MUXREG(uart0_pins, 0, PMX_UART0_MASK, 0); +DEFINE_MUXREG(timer_0_1_pins, 0, PMX_TIMER_0_1_MASK, 0); +DEFINE_MUXREG(timer_2_3_pins, 0, PMX_TIMER_2_3_MASK, 0); + +static struct spear_gpio_pingroup spear3xx_gpio_pingroup[] = { + GPIO_PINGROUP(firda_pins), + GPIO_PINGROUP(i2c_pins), + GPIO_PINGROUP(ssp_cs_pins), + GPIO_PINGROUP(ssp_pins), + GPIO_PINGROUP(mii_pins), + GPIO_PINGROUP(gpio0_pin0_pins), + GPIO_PINGROUP(gpio0_pin1_pins), + GPIO_PINGROUP(gpio0_pin2_pins), + GPIO_PINGROUP(gpio0_pin3_pins), + GPIO_PINGROUP(gpio0_pin4_pins), + GPIO_PINGROUP(gpio0_pin5_pins), + GPIO_PINGROUP(uart0_ext_pins), + GPIO_PINGROUP(uart0_pins), + GPIO_PINGROUP(timer_0_1_pins), + GPIO_PINGROUP(timer_2_3_pins), +}; + struct spear_pinctrl_machdata spear3xx_machdata = { .pins = spear3xx_pins, .npins = ARRAY_SIZE(spear3xx_pins), + .gpio_pingroups = spear3xx_gpio_pingroup, + .ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup), }; diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 3d7e1ee2fa57a4a6db1deb0a7a173b90769298a3..65f891be12d1d6481849f93ce4d06e8ec6373a17 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -1773,6 +1774,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) struct atmel_uart_data *pdata = pdev->dev.platform_data; void *data; int ret = -ENODEV; + struct pinctrl *pinctrl; BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); @@ -1805,6 +1807,12 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) atmel_init_port(port, pdev); + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + ret = PTR_ERR(pinctrl); + goto err; + } + if (!atmel_use_dma_rx(&port->uart)) { ret = -ENOMEM; data = kmalloc(sizeof(struct atmel_uart_char) diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index a9432fc6b8ba7ade0b50d85c2582e81998c301fe..9fd3093d855a14582b4d5ccb29ad95178edd309f 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -5,6 +5,7 @@ #include #include #include +#include #ifdef CONFIG_GPIOLIB @@ -134,6 +135,15 @@ struct gpio_chip { int (*of_xlate)(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags); #endif +#ifdef CONFIG_PINCTRL + /* + * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally + * describe the actual pin range which they serve in an SoC. This + * information would be used by pinctrl subsystem to configure + * corresponding pins for gpio usage. + */ + struct list_head pin_ranges; +#endif }; extern const char *gpiochip_is_requested(struct gpio_chip *chip, @@ -257,4 +267,41 @@ static inline void gpio_unexport(unsigned gpio) } #endif /* CONFIG_GPIO_SYSFS */ +#ifdef CONFIG_PINCTRL + +/** + * struct gpio_pin_range - pin range controlled by a gpio chip + * @head: list for maintaining set of pin ranges, used internally + * @pctldev: pinctrl device which handles corresponding pins + * @range: actual range of pins controlled by a gpio controller + */ + +struct gpio_pin_range { + struct list_head node; + struct pinctrl_dev *pctldev; + struct pinctrl_gpio_range range; +}; + +int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, + unsigned int gpio_offset, unsigned int pin_offset, + unsigned int npins); +void gpiochip_remove_pin_ranges(struct gpio_chip *chip); + +#else + +static inline int +gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, + unsigned int gpio_offset, unsigned int pin_offset, + unsigned int npins) +{ + return 0; +} + +static inline void +gpiochip_remove_pin_ranges(struct gpio_chip *chip) +{ +} + +#endif /* CONFIG_PINCTRL */ + #endif /* _ASM_GENERIC_GPIO_H */ diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 2e31e8b3a190bb652bb597104139d2f2b440d347..bfe665621536bc324680ca6ca24b7c65d85f611f 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -72,9 +72,9 @@ static inline int irq_to_gpio(unsigned int irq) return -EINVAL; } -#endif +#endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */ -#else +#else /* ! CONFIG_GENERIC_GPIO */ #include #include @@ -231,6 +231,21 @@ static inline int irq_to_gpio(unsigned irq) return -EINVAL; } -#endif +static inline int +gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, + unsigned int gpio_offset, unsigned int pin_offset, + unsigned int npins) +{ + WARN_ON(1); + return -EINVAL; +} + +static inline void +gpiochip_remove_pin_ranges(struct gpio_chip *chip) +{ + WARN_ON(1); +} + +#endif /* ! CONFIG_GENERIC_GPIO */ #endif /* __LINUX_GPIO_H */ diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h index 4f0abb9f1c092a169b4215b833c613eac30962c2..47a1bdd88878da4b6a7be614b654b8b0ce228006 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -46,11 +46,11 @@ * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source * (open emitter). Sending this config will enabale open drain mode, the * argument is ignored. + * @PIN_CONFIG_INPUT_SCHMITT_DISABLE: disable schmitt-trigger mode on the pin. * @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in * schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis, * the threshold value is given on a custom format as argument when - * setting pins to this mode. The argument zero turns the schmitt trigger - * off. + * setting pins to this mode. * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode, * which means it will wait for signals to settle when reading inputs. The * argument gives the debounce time on a custom format. Setting the @@ -74,6 +74,7 @@ enum pin_config_param { PIN_CONFIG_DRIVE_PUSH_PULL, PIN_CONFIG_DRIVE_OPEN_DRAIN, PIN_CONFIG_DRIVE_OPEN_SOURCE, + PIN_CONFIG_INPUT_SCHMITT_DISABLE, PIN_CONFIG_INPUT_SCHMITT, PIN_CONFIG_INPUT_DEBOUNCE, PIN_CONFIG_POWER_SOURCE, diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 7d087f03e91ec3c57e92d843f575d7df66fb9544..04d6700d99afd610a9a002d8ddc70f0dd33b09ca 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -134,6 +134,25 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *ranges, unsigned nranges); +extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range); + +extern struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname, + struct pinctrl_gpio_range *range); +extern struct pinctrl_gpio_range * +pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, + unsigned int pin); + +#ifdef CONFIG_OF +extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np); +#else +static inline +struct pinctrl_dev *of_pinctrl_get(struct device_node *np) +{ + return NULL; +} +#endif /* CONFIG_OF */ + extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev); extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev); #else diff --git a/include/linux/platform_data/pinctrl-coh901.h b/include/linux/platform_data/pinctrl-coh901.h index 30dea251b835b3433af3fd93a840a2d70a91cc57..dfbc65d10484a0d80d8a92b641a78c822fd7ffb3 100644 --- a/include/linux/platform_data/pinctrl-coh901.h +++ b/include/linux/platform_data/pinctrl-coh901.h @@ -13,14 +13,10 @@ * struct u300_gpio_platform - U300 GPIO platform data * @ports: number of GPIO block ports * @gpio_base: first GPIO number for this block (use a free range) - * @gpio_irq_base: first GPIO IRQ number for this block (use a free range) - * @pinctrl_device: pin control device to spawn as child */ struct u300_gpio_platform { u8 ports; int gpio_base; - int gpio_irq_base; - struct platform_device *pinctrl_device; }; #endif /* __MACH_U300_GPIO_U300_H */ diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/include/linux/platform_data/pinctrl-nomadik.h similarity index 66% rename from arch/arm/plat-nomadik/include/plat/pincfg.h rename to include/linux/platform_data/pinctrl-nomadik.h index 3b8ec60af351500a5cbcb80c970b8026c7d8477d..f73b2f0c55b77f6fc61605f6315563494d6692fc 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/include/linux/platform_data/pinctrl-nomadik.h @@ -1,16 +1,17 @@ /* - * Copyright (C) ST-Ericsson SA 2010 + * Structures and registers for GPIO access in the Nomadik SoC * - * License terms: GNU General Public License, version 2 - * Author: Rabin Vincent for ST-Ericsson + * Copyright (C) 2008 STMicroelectronics + * Author: Prafulla WADASKAR + * Copyright (C) 2009 Alessandro Rubini * - * Based on arch/arm/mach-pxa/include/mach/mfp.h: - * Copyright (C) 2007 Marvell International Ltd. - * eric miao + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. */ -#ifndef __PLAT_PINCFG_H -#define __PLAT_PINCFG_H +#ifndef __PLAT_NOMADIK_GPIO +#define __PLAT_NOMADIK_GPIO /* * pin configurations are represented by 32-bit integers: @@ -166,8 +167,100 @@ typedef unsigned long pin_cfg_t; (PIN_CFG_DEFAULT |\ (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +#define GPIO_BLOCK_SHIFT 5 +#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT) + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 +#define NMK_GPIO_LOWEMI 0x28 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 +/* These appear in DB8540 and later ASICs */ +#define NMK_GPIO_EDGELEVEL 0x5C +#define NMK_GPIO_LEVEL 0x60 + +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +#define NMK_GPIO_ALT_CX_SHIFT 2 +#define NMK_GPIO_ALT_C1 ((1<