diff options
110 files changed, 4904 insertions, 653 deletions
diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt new file mode 100644 index 000000000000..cd5e23912888 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt @@ -0,0 +1,339 @@ +Device Tree Clock bindings for arch-at91 + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible : shall be one of the following: + "atmel,at91rm9200-pmc" or + "atmel,at91sam9g45-pmc" or + "atmel,at91sam9n12-pmc" or + "atmel,at91sam9x5-pmc" or + "atmel,sama5d3-pmc": + at91 PMC (Power Management Controller) + All at91 specific clocks (clocks defined below) must be child + node of the PMC node. + + "atmel,at91rm9200-clk-main": + at91 main oscillator + + "atmel,at91rm9200-clk-master" or + "atmel,at91sam9x5-clk-master": + at91 master clock + + "atmel,at91sam9x5-clk-peripheral" or + "atmel,at91rm9200-clk-peripheral": + at91 peripheral clocks + + "atmel,at91rm9200-clk-pll" or + "atmel,at91sam9g45-clk-pll" or + "atmel,at91sam9g20-clk-pllb" or + "atmel,sama5d3-clk-pll": + at91 pll clocks + + "atmel,at91sam9x5-clk-plldiv": + at91 plla divisor + + "atmel,at91rm9200-clk-programmable" or + "atmel,at91sam9g45-clk-programmable" or + "atmel,at91sam9x5-clk-programmable": + at91 programmable clocks + + "atmel,at91sam9x5-clk-smd": + at91 SMD (Soft Modem) clock + + "atmel,at91rm9200-clk-system": + at91 system clocks + + "atmel,at91rm9200-clk-usb" or + "atmel,at91sam9x5-clk-usb" or + "atmel,at91sam9n12-clk-usb": + at91 usb clock + + "atmel,at91sam9x5-clk-utmi": + at91 utmi clock + +Required properties for PMC node: +- reg : defines the IO memory reserved for the PMC. +- #size-cells : shall be 0 (reg is used to encode clk id). +- #address-cells : shall be 1 (reg is used to encode clk id). +- interrupts : shall be set to PMC interrupt line. +- interrupt-controller : tell that the PMC is an interrupt controller. +- #interrupt-cells : must be set to 1. The first cell encodes the interrupt id, + and reflect the bit position in the PMC_ER/DR/SR registers. + You can use the dt macros defined in dt-bindings/clk/at91.h. + 0 (AT91_PMC_MOSCS) -> main oscillator ready + 1 (AT91_PMC_LOCKA) -> PLL A ready + 2 (AT91_PMC_LOCKB) -> PLL B ready + 3 (AT91_PMC_MCKRDY) -> master clock ready + 6 (AT91_PMC_LOCKU) -> UTMI PLL clock ready + 8 .. 15 (AT91_PMC_PCKRDY(id)) -> programmable clock ready + 16 (AT91_PMC_MOSCSELS) -> main oscillator selected + 17 (AT91_PMC_MOSCRCS) -> RC main oscillator stabilized + 18 (AT91_PMC_CFDEV) -> clock failure detected + +For example: + pmc: pmc@fffffc00 { + compatible = "atmel,sama5d3-pmc"; + interrupts = <1 4 7>; + interrupt-controller; + #interrupt-cells = <2>; + #size-cells = <0>; + #address-cells = <1>; + + /* put at91 clocks here */ + }; + +Required properties for main clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to "<0>". +- #clock-cells : from common clock binding; shall be set to 0. +- clocks (optional if clock-frequency is provided) : shall be the slow clock + phandle. This clock is used to calculate the main clock rate if + "clock-frequency" is not provided. +- clock-frequency : the main oscillator frequency.Prefer the use of + "clock-frequency" over automatic clock rate calculation. + +For example: + main: mainck { + compatible = "atmel,at91rm9200-clk-main"; + interrupt-parent = <&pmc>; + interrupts = <0>; + #clock-cells = <0>; + clocks = <&ck32k>; + clock-frequency = <18432000>; + }; + +Required properties for master clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to "<3>". +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the master clock sources (see atmel datasheet) phandles. + e.g. "<&ck32k>, <&main>, <&plla>, <&pllb>". +- atmel,clk-output-range : minimum and maximum clock frequency (two u32 + fields). + e.g. output = <0 133000000>; <=> 0 to 133MHz. +- atmel,clk-divisors : master clock divisors table (four u32 fields). + 0 <=> reserved value. + e.g. divisors = <1 2 4 6>; +- atmel,master-clk-have-div3-pres : some SoC use the reserved value 7 in the + PRES field as CLOCK_DIV3 (e.g sam9x5). + +For example: + mck: mck { + compatible = "atmel,at91rm9200-clk-master"; + interrupt-parent = <&pmc>; + interrupts = <3>; + #clock-cells = <0>; + atmel,clk-output-range = <0 133000000>; + atmel,clk-divisors = <1 2 4 0>; + }; + +Required properties for peripheral clocks: +- #size-cells : shall be 0 (reg is used to encode clk id). +- #address-cells : shall be 1 (reg is used to encode clk id). +- clocks : shall be the master clock phandle. + e.g. clocks = <&mck>; +- name: device tree node describing a specific system clock. + * #clock-cells : from common clock binding; shall be set to 0. + * reg: peripheral id. See Atmel's datasheets to get a full + list of peripheral ids. + * atmel,clk-output-range : minimum and maximum clock frequency + (two u32 fields). Only valid on at91sam9x5-clk-peripheral + compatible IPs. + +For example: + periph: periphck { + compatible = "atmel,at91sam9x5-clk-peripheral"; + #size-cells = <0>; + #address-cells = <1>; + clocks = <&mck>; + + ssc0_clk { + #clock-cells = <0>; + reg = <2>; + atmel,clk-output-range = <0 133000000>; + }; + + usart0_clk { + #clock-cells = <0>; + reg = <3>; + atmel,clk-output-range = <0 66000000>; + }; + }; + + +Required properties for pll clocks: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to "<1>". +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the main clock phandle. +- reg : pll id. + 0 -> PLL A + 1 -> PLL B +- atmel,clk-input-range : minimum and maximum source clock frequency (two u32 + fields). + e.g. input = <1 32000000>; <=> 1 to 32MHz. +- #atmel,pll-clk-output-range-cells : number of cells reserved for pll output + range description. Sould be set to 2, 3 + or 4. + * 1st and 2nd cells represent the frequency range (min-max). + * 3rd cell is optional and represents the OUT field value for the given + range. + * 4th cell is optional and represents the ICPLL field (PLLICPR + register) +- atmel,pll-clk-output-ranges : pll output frequency ranges + optional parameter + depending on #atmel,pll-output-range-cells + property value. + +For example: + plla: pllack { + compatible = "atmel,at91sam9g45-clk-pll"; + interrupt-parent = <&pmc>; + interrupts = <1>; + #clock-cells = <0>; + clocks = <&main>; + reg = <0>; + atmel,clk-input-range = <2000000 32000000>; + #atmel,pll-clk-output-range-cells = <4>; + atmel,pll-clk-output-ranges = <74500000 800000000 0 0 + 69500000 750000000 1 0 + 64500000 700000000 2 0 + 59500000 650000000 3 0 + 54500000 600000000 0 1 + 49500000 550000000 1 1 + 44500000 500000000 2 1 + 40000000 450000000 3 1>; + }; + +Required properties for plldiv clocks (plldiv = pll / 2): +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the plla clock phandle. + +The pll divisor is equal to 2 and cannot be changed. + +For example: + plladiv: plladivck { + compatible = "atmel,at91sam9x5-clk-plldiv"; + #clock-cells = <0>; + clocks = <&plla>; + }; + +Required properties for programmable clocks: +- interrupt-parent : must reference the PMC node. +- #size-cells : shall be 0 (reg is used to encode clk id). +- #address-cells : shall be 1 (reg is used to encode clk id). +- clocks : shall be the programmable clock source phandles. + e.g. clocks = <&clk32k>, <&main>, <&plla>, <&pllb>; +- name: device tree node describing a specific prog clock. + * #clock-cells : from common clock binding; shall be set to 0. + * reg : programmable clock id (register offset from PCKx + register). + * interrupts : shall be set to "<(8 + id)>". + +For example: + prog: progck { + compatible = "atmel,at91sam9g45-clk-programmable"; + #size-cells = <0>; + #address-cells = <1>; + interrupt-parent = <&pmc>; + clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>; + + prog0 { + #clock-cells = <0>; + reg = <0>; + interrupts = <8>; + }; + + prog1 { + #clock-cells = <0>; + reg = <1>; + interrupts = <9>; + }; + }; + + +Required properties for smd clock: +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the smd clock source phandles. + e.g. clocks = <&plladiv>, <&utmi>; + +For example: + smd: smdck { + compatible = "atmel,at91sam9x5-clk-smd"; + #clock-cells = <0>; + clocks = <&plladiv>, <&utmi>; + }; + +Required properties for system clocks: +- #size-cells : shall be 0 (reg is used to encode clk id). +- #address-cells : shall be 1 (reg is used to encode clk id). +- name: device tree node describing a specific system clock. + * #clock-cells : from common clock binding; shall be set to 0. + * reg: system clock id (bit position in SCER/SCDR/SCSR registers). + See Atmel's datasheet to get a full list of system clock ids. + +For example: + system: systemck { + compatible = "atmel,at91rm9200-clk-system"; + #address-cells = <1>; + #size-cells = <0>; + + ddrck { + #clock-cells = <0>; + reg = <2>; + clocks = <&mck>; + }; + + uhpck { + #clock-cells = <0>; + reg = <6>; + clocks = <&usb>; + }; + + udpck { + #clock-cells = <0>; + reg = <7>; + clocks = <&usb>; + }; + }; + + +Required properties for usb clock: +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the smd clock source phandles. + e.g. clocks = <&pllb>; +- atmel,clk-divisors (only available for "atmel,at91rm9200-clk-usb"): + usb clock divisor table. + e.g. divisors = <1 2 4 0>; + +For example: + usb: usbck { + compatible = "atmel,at91sam9x5-clk-usb"; + #clock-cells = <0>; + clocks = <&plladiv>, <&utmi>; + }; + + usb: usbck { + compatible = "atmel,at91rm9200-clk-usb"; + #clock-cells = <0>; + clocks = <&pllb>; + atmel,clk-divisors = <1 2 4 0>; + }; + + +Required properties for utmi clock: +- interrupt-parent : must reference the PMC node. +- interrupts : shall be set to "<AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>". +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : shall be the main clock source phandle. + +For example: + utmi: utmick { + compatible = "atmel,at91sam9x5-clk-utmi"; + interrupt-parent = <&pmc>; + interrupts = <AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>; + #clock-cells = <0>; + clocks = <&main>; + }; diff --git a/Documentation/devicetree/bindings/mmc/ti-omap.txt b/Documentation/devicetree/bindings/mmc/ti-omap.txt new file mode 100644 index 000000000000..8de579969763 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/ti-omap.txt @@ -0,0 +1,54 @@ +* TI MMC host controller for OMAP1 and 2420 + +The MMC Host Controller on TI OMAP1 and 2420 family provides +an interface for MMC, SD, and SDIO types of memory cards. + +This file documents differences between the core properties described +by mmc.txt and the properties used by the omap mmc driver. + +Note that this driver will not work with omap2430 or later omaps, +please see the omap hsmmc driver for the current omaps. + +Required properties: +- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers +- ti,hwmods: For 2420, must be "msdi<n>", where n is controller + instance starting 1 + +Examples: + + msdi1: mmc@4809c000 { + compatible = "ti,omap2420-mmc"; + ti,hwmods = "msdi1"; + reg = <0x4809c000 0x80>; + interrupts = <83>; + dmas = <&sdma 61 &sdma 62>; + dma-names = "tx", "rx"; + }; + +* TI MMC host controller for OMAP1 and 2420 + +The MMC Host Controller on TI OMAP1 and 2420 family provides +an interface for MMC, SD, and SDIO types of memory cards. + +This file documents differences between the core properties described +by mmc.txt and the properties used by the omap mmc driver. + +Note that this driver will not work with omap2430 or later omaps, +please see the omap hsmmc driver for the current omaps. + +Required properties: +- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers +- ti,hwmods: For 2420, must be "msdi<n>", where n is controller + instance starting 1 + +Examples: + + msdi1: mmc@4809c000 { + compatible = "ti,omap2420-mmc"; + ti,hwmods = "msdi1"; + reg = <0x4809c000 0x80>; + interrupts = <83>; + dmas = <&sdma 61 &sdma 62>; + dma-names = "tx", "rx"; + }; + diff --git a/arch/arm/boot/dts/am335x-base0033.dts b/arch/arm/boot/dts/am335x-base0033.dts index b4f95c2bbf74..72a9b3fc4251 100644 --- a/arch/arm/boot/dts/am335x-base0033.dts +++ b/arch/arm/boot/dts/am335x-base0033.dts @@ -13,4 +13,83 @@ / { model = "IGEP COM AM335x on AQUILA Expansion"; compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx"; + + hdmi { + compatible = "ti,tilcdc,slave"; + i2c = <&i2c0>; + pinctrl-names = "default", "off"; + pinctrl-0 = <&nxp_hdmi_pins>; + pinctrl-1 = <&nxp_hdmi_off_pins>; + status = "okay"; + }; + + leds_base { + pinctrl-names = "default"; + pinctrl-0 = <&leds_base_pins>; + + compatible = "gpio-leds"; + + led@0 { + label = "base:red:user"; + gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; /* gpio1_21 */ + default-state = "off"; + }; + + led@1 { + label = "base:green:user"; + gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; /* gpio2_0 */ + default-state = "off"; + }; + }; +}; + +&am33xx_pinmux { + nxp_hdmi_pins: pinmux_nxp_hdmi_pins { + pinctrl-single,pins = < + 0x1b0 (PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */ + 0xa0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data0 */ + 0xa4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data1 */ + 0xa8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data2 */ + 0xac (PIN_OUTPUT | MUX_MODE0) /* lcd_data3 */ + 0xb0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data4 */ + 0xb4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data5 */ + 0xb8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data6 */ + 0xbc (PIN_OUTPUT | MUX_MODE0) /* lcd_data7 */ + 0xc0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data8 */ + 0xc4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data9 */ + 0xc8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data10 */ + 0xcc (PIN_OUTPUT | MUX_MODE0) /* lcd_data11 */ + 0xd0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data12 */ + 0xd4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data13 */ + 0xd8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data14 */ + 0xdc (PIN_OUTPUT | MUX_MODE0) /* lcd_data15 */ + 0xe0 (PIN_OUTPUT | MUX_MODE0) /* lcd_vsync */ + 0xe4 (PIN_OUTPUT | MUX_MODE0) /* lcd_hsync */ + 0xe8 (PIN_OUTPUT | MUX_MODE0) /* lcd_pclk */ + 0xec (PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en */ + >; + }; + nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins { + pinctrl-single,pins = < + 0x1b0 (PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */ + >; + }; + + leds_base_pins: pinmux_leds_base_pins { + pinctrl-single,pins = < + 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */ + 0x88 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn3.gpio2_0 */ + >; + }; +}; + +&lcdc { + status = "okay"; +}; + +&i2c0 { + eeprom: eeprom@50 { + compatible = "at,24c256"; + reg = <0x50>; + }; }; diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/am335x-igep0033.dtsi index 619624479311..7063311a58d9 100644 --- a/arch/arm/boot/dts/am335x-igep0033.dtsi +++ b/arch/arm/boot/dts/am335x-igep0033.dtsi @@ -199,6 +199,35 @@ pinctrl-0 = <&uart0_pins>; }; +&usb { + status = "okay"; + + control@44e10000 { + status = "okay"; + }; + + usb-phy@47401300 { + status = "okay"; + }; + + usb-phy@47401b00 { + status = "okay"; + }; + + usb@47401000 { + status = "okay"; + }; + + usb@47401800 { + status = "okay"; + dr_mode = "host"; + }; + + dma-controller@07402000 { + status = "okay"; + }; +}; + #include "tps65910.dtsi" &tps { diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 90ce29dbe119..08a56bcfc724 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts @@ -99,22 +99,22 @@ spi-max-frequency = <50000000>; }; }; + }; - pcie-controller { + pcie-controller { + status = "okay"; + /* + * The two PCIe units are accessible through + * both standard PCIe slots and mini-PCIe + * slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie@2,0 { + /* Port 1, Lane 0 */ status = "okay"; - /* - * The two PCIe units are accessible through - * both standard PCIe slots and mini-PCIe - * slots on the board. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ - status = "okay"; - }; - pcie@2,0 { - /* Port 1, Lane 0 */ - status = "okay"; - }; }; }; }; diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index f2b6ae4f55d0..45839e53538e 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -118,7 +118,7 @@ coherency-fabric@20200 { compatible = "marvell,coherency-fabric"; - reg = <0x20200 0xb0>, <0x21810 0x1c>; + reg = <0x20200 0xb0>, <0x21010 0x1c>; }; serial@12000 { diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi index 3f5e6121c730..98335fb34b7a 100644 --- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi @@ -47,7 +47,7 @@ /* * MV78230 has 2 PCIe units Gen2.0: One unit can be * configured as x4 or quad x1 lanes. One unit is - * x4/x1. + * x1 only. */ pcie-controller { compatible = "marvell,armada-xp-pcie"; @@ -62,10 +62,10 @@ ranges = <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */ - 0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000 /* Port 2.0 registers */ 0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 /* Port 0.1 registers */ 0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */ 0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */ + 0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 /* Port 1.0 registers */ 0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */ 0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */ 0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */ @@ -74,8 +74,8 @@ 0x81000000 0x3 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO */ 0x82000000 0x4 0 MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */ 0x81000000 0x4 0 MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO */ - 0x82000000 0x9 0 MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */ - 0x81000000 0x9 0 MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO */>; + 0x82000000 0x5 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */ + 0x81000000 0x5 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */>; pcie@1,0 { device_type = "pci"; @@ -145,20 +145,20 @@ status = "disabled"; }; - pcie@9,0 { + pcie@5,0 { device_type = "pci"; - assigned-addresses = <0x82000800 0 0x42000 0 0x2000>; - reg = <0x4800 0 0 0 0>; + assigned-addresses = <0x82000800 0 0x80000 0 0x2000>; + reg = <0x2800 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; - ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0 - 0x81000000 0 0 0x81000000 0x9 0 1 0>; + ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0 + 0x81000000 0 0 0x81000000 0x5 0 1 0>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 99>; - marvell,pcie-port = <2>; + interrupt-map = <0 0 0 0 &mpic 62>; + marvell,pcie-port = <1>; marvell,pcie-lane = <0>; - clocks = <&gateclk 26>; + clocks = <&gateclk 9>; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi index 3e9fd1353f89..66609684d41b 100644 --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi @@ -48,7 +48,7 @@ /* * MV78260 has 3 PCIe units Gen2.0: Two units can be * configured as x4 or quad x1 lanes. One unit is - * x4/x1. + * x4 only. */ pcie-controller { compatible = "marvell,armada-xp-pcie"; @@ -68,7 +68,9 @@ 0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */ 0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */ 0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 /* Port 1.0 registers */ - 0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000 /* Port 3.0 registers */ + 0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000 /* Port 1.1 registers */ + 0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000 /* Port 1.2 registers */ + 0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000 /* Port 1.3 registers */ 0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */ 0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */ 0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */ @@ -77,10 +79,18 @@ 0x81000000 0x3 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO */ 0x82000000 0x4 0 MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */ 0x81000000 0x4 0 MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO */ - 0x82000000 0x9 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */ - 0x81000000 0x9 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */ - 0x82000000 0xa 0 MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */ - 0x81000000 0xa 0 MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO */>; + + 0x82000000 0x5 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */ + 0x81000000 0x5 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */ + 0x82000000 0x6 0 MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */ + 0x81000000 0x6 0 MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO */ + 0x82000000 0x7 0 MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */ + 0x81000000 0x7 0 MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO */ + 0x82000000 0x8 0 MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */ + 0x81000000 0x8 0 MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO */ + + 0x82000000 0x9 0 MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */ + 0x81000000 0x9 0 MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO */>; pcie@1,0 { device_type = "pci"; @@ -106,8 +116,8 @@ #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; - ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0 - 0x81000000 0 0 0x81000000 0x2 0 1 0>; + ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0 + 0x81000000 0 0 0x81000000 0x2 0 1 0>; interrupt-map-mask = <0 0 0 0>; interrupt-map = <0 0 0 0 &mpic 59>; marvell,pcie-port = <0>; @@ -150,37 +160,88 @@ status = "disabled"; }; - pcie@9,0 { + pcie@5,0 { device_type = "pci"; - assigned-addresses = <0x82000800 0 0x42000 0 0x2000>; - reg = <0x4800 0 0 0 0>; + assigned-addresses = <0x82000800 0 0x80000 0 0x2000>; + reg = <0x2800 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; - ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0 - 0x81000000 0 0 0x81000000 0x9 0 1 0>; + ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0 + 0x81000000 0 0 0x81000000 0x5 0 1 0>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 99>; - marvell,pcie-port = <2>; + interrupt-map = <0 0 0 0 &mpic 62>; + marvell,pcie-port = <1>; marvell,pcie-lane = <0>; - clocks = <&gateclk 26>; + clocks = <&gateclk 9>; status = "disabled"; }; - pcie@10,0 { + pcie@6,0 { device_type = "pci"; - assigned-addresses = <0x82000800 0 0x82000 0 0x2000>; - reg = <0x5000 0 0 0 0>; + assigned-addresses = <0x82000800 0 0x84000 0 0x2000>; + reg = <0x3000 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; - ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0 - 0x81000000 0 0 0x81000000 0xa 0 1 0>; + ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0 + 0x81000000 0 0 0x81000000 0x6 0 1 0>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 103>; - marvell,pcie-port = <3>; + interrupt-map = <0 0 0 0 &mpic 63>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 10>; + status = "disabled"; + }; + + pcie@7,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x88000 0 0x2000>; + reg = <0x3800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0 + 0x81000000 0 0 0x81000000 0x7 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 64>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <2>; + clocks = <&gateclk 11>; + status = "disabled"; + }; + + pcie@8,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>; + reg = <0x4000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0 + 0x81000000 0 0 0x81000000 0x8 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 65>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <3>; + clocks = <&gateclk 12>; + status = "disabled"; + }; + + pcie@9,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x42000 0 0x2000>; + reg = <0x4800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0 + 0x81000000 0 0 0x81000000 0x9 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 99>; + marvell,pcie-port = <2>; marvell,pcie-lane = <0>; - clocks = <&gateclk 27>; + clocks = <&gateclk 26>; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/at91sam9x5_usart3.dtsi b/arch/arm/boot/dts/at91sam9x5_usart3.dtsi index 2347e9563cef..6801106fa1f8 100644 --- a/arch/arm/boot/dts/at91sam9x5_usart3.dtsi +++ b/arch/arm/boot/dts/at91sam9x5_usart3.dtsi @@ -11,6 +11,10 @@ #include <dt-bindings/interrupt-controller/irq.h> / { + aliases { + serial4 = &usart3; + }; + ahb { apb { pinctrl@fffff400 { diff --git a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi index 9c18adf788f7..f577b7df9a29 100644 --- a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi +++ b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi @@ -44,8 +44,8 @@ gpmc,wr-access-ns = <186>; gpmc,cycle2cycle-samecsen; gpmc,cycle2cycle-diffcsen; - vmmc-supply = <&vddvario>; - vmmc_aux-supply = <&vdd33a>; + vddvario-supply = <&vddvario>; + vdd33a-supply = <&vdd33a>; reg-io-width = <4>; smsc,save-mac-address; }; diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts index 31a632f7effb..df33a50bc070 100644 --- a/arch/arm/boot/dts/omap3-beagle-xm.dts +++ b/arch/arm/boot/dts/omap3-beagle-xm.dts @@ -215,3 +215,10 @@ &usbhsehci { phys = <0 &hsusb2_phy>; }; + +&vaux2 { + regulator-name = "usb_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; +}; diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts index fa532aaacc68..3ba4a625ea5b 100644 --- a/arch/arm/boot/dts/omap3-beagle.dts +++ b/arch/arm/boot/dts/omap3-beagle.dts @@ -61,6 +61,14 @@ vcc-supply = <&hsusb2_power>; }; + sound { + compatible = "ti,omap-twl4030"; + ti,model = "omap3beagle"; + + ti,mcbsp = <&mcbsp2>; + ti,codec = <&twl_audio>; + }; + gpio_keys { compatible = "gpio-keys"; @@ -120,6 +128,12 @@ reg = <0x48>; interrupts = <7>; /* SYS_NIRQ cascaded to intc */ interrupt-parent = <&intc>; + + twl_audio: audio { + compatible = "ti,twl4030-audio"; + codec { + }; + }; }; }; @@ -178,3 +192,10 @@ mode = <3>; power = <50>; }; + +&vaux2 { + regulator-name = "vdd_ehci"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; +}; diff --git a/arch/arm/boot/dts/omap3-igep.dtsi b/arch/arm/boot/dts/omap3-igep.dtsi index ba1e58b7b7e3..165aaf7591ba 100644 --- a/arch/arm/boot/dts/omap3-igep.dtsi +++ b/arch/arm/boot/dts/omap3-igep.dtsi @@ -1,5 +1,5 @@ /* - * Device Tree Source for IGEP Technology devices + * Common device tree for IGEP boards based on AM/DM37x * * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk> * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com> @@ -10,7 +10,7 @@ */ /dts-v1/; -#include "omap34xx.dtsi" +#include "omap36xx.dtsi" / { memory { @@ -24,6 +24,25 @@ ti,mcbsp = <&mcbsp2>; ti,codec = <&twl_audio>; }; + + vdd33: regulator-vdd33 { + compatible = "regulator-fixed"; + regulator-name = "vdd33"; + regulator-always-on; + }; + + lbee1usjyc_vmmc: lbee1usjyc_vmmc { + pinctrl-names = "default"; + pinctrl-0 = <&lbee1usjyc_pins>; + compatible = "regulator-fixed"; + regulator-name = "regulator-lbee1usjyc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>; /* gpio_138 WIFI_PDN */ + startup-delay-us = <10000>; + enable-active-high; + vin-supply = <&vdd33>; + }; }; &omap3_pmx_core { @@ -48,6 +67,15 @@ >; }; + /* WiFi/BT combo */ + lbee1usjyc_pins: pinmux_lbee1usjyc_pins { + pinctrl-single,pins = < + 0x136 (PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat5.gpio_137 */ + 0x138 (PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat6.gpio_138 */ + 0x13a (PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat7.gpio_139 */ + >; + }; + mcbsp2_pins: pinmux_mcbsp2_pins { pinctrl-single,pins = < 0x10c (PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ @@ -65,10 +93,17 @@ 0x11a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat1.sdmmc1_dat1 */ 0x11c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat2.sdmmc1_dat2 */ 0x11e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */ - 0x120 (PIN_INPUT | MUX_MODE0) /* sdmmc1_dat4.sdmmc1_dat4 */ - 0x122 (PIN_INPUT | MUX_MODE0) /* sdmmc1_dat5.sdmmc1_dat5 */ - 0x124 (PIN_INPUT | MUX_MODE0) /* sdmmc1_dat6.sdmmc1_dat6 */ - 0x126 (PIN_INPUT | MUX_MODE0) /* sdmmc1_dat7.sdmmc1_dat7 */ + >; + }; + + mmc2_pins: pinmux_mmc2_pins { + pinctrl-single,pins = < + 0x128 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ + 0x12a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ + 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0.sdmmc2_dat0 */ + 0x12e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */ + 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat2.sdmmc2_dat2 */ + 0x132 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat3.sdmmc2_dat3 */ >; }; @@ -78,10 +113,33 @@ >; }; + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + 0x18a (PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ + 0x18c (PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + 0x18e (PIN_INPUT | MUX_MODE0) /* i2c2_scl.i2c2_scl */ + 0x190 (PIN_INPUT | MUX_MODE0) /* i2c2_sda.i2c2_sda */ + >; + }; + + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + 0x192 (PIN_INPUT | MUX_MODE0) /* i2c3_scl.i2c3_scl */ + 0x194 (PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ + >; + }; + leds_pins: pinmux_leds_pins { }; }; &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; clock-frequency = <2600000>; twl: twl@48 { @@ -101,9 +159,16 @@ #include "twl4030_omap3.dtsi" &i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; clock-frequency = <400000>; }; +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; +}; + &mcbsp2 { pinctrl-names = "default"; pinctrl-0 = <&mcbsp2_pins>; @@ -114,11 +179,15 @@ pinctrl-0 = <&mmc1_pins>; vmmc-supply = <&vmmc1>; vmmc_aux-supply = <&vsim>; - bus-width = <8>; + bus-width = <4>; }; &mmc2 { - status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <&lbee1usjyc_vmmc>; + bus-width = <4>; + non-removable; }; &mmc3 { diff --git a/arch/arm/boot/dts/omap3-igep0020.dts b/arch/arm/boot/dts/omap3-igep0020.dts index d5cc79267250..1c7e74d2d2bc 100644 --- a/arch/arm/boot/dts/omap3-igep0020.dts +++ b/arch/arm/boot/dts/omap3-igep0020.dts @@ -1,5 +1,5 @@ /* - * Device Tree Source for IGEPv2 board + * Device Tree Source for IGEPv2 Rev. (TI OMAP AM/DM37x) * * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk> * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com> @@ -13,7 +13,7 @@ #include "omap-gpmc-smsc911x.dtsi" / { - model = "IGEPv2"; + model = "IGEPv2 (TI OMAP AM/DM37x)"; compatible = "isee,omap3-igep0020", "ti,omap3"; leds { @@ -67,6 +67,8 @@ pinctrl-names = "default"; pinctrl-0 = < &hsusbb1_pins + &tfp410_pins + &dss_pins >; hsusbb1_pins: pinmux_hsusbb1_pins { @@ -85,6 +87,45 @@ 0x5ba (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d7.hsusb1_data3 */ >; }; + + tfp410_pins: tfp410_dvi_pins { + pinctrl-single,pins = < + 0x196 (PIN_OUTPUT | MUX_MODE4) /* hdq_sio.gpio_170 */ + >; + }; + + dss_pins: pinmux_dss_dvi_pins { + pinctrl-single,pins = < + 0x0a4 (PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ + 0x0a6 (PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ + 0x0a8 (PIN_OUTPUT | MUX_MODE0) /* dss_vsync.dss_vsync */ + 0x0aa (PIN_OUTPUT | MUX_MODE0) /* dss_acbias.dss_acbias */ + 0x0ac (PIN_OUTPUT | MUX_MODE0) /* dss_data0.dss_data0 */ + 0x0ae (PIN_OUTPUT | MUX_MODE0) /* dss_data1.dss_data1 */ + 0x0b0 (PIN_OUTPUT | MUX_MODE0) /* dss_data2.dss_data2 */ + 0x0b2 (PIN_OUTPUT | MUX_MODE0) /* dss_data3.dss_data3 */ + 0x0b4 (PIN_OUTPUT | MUX_MODE0) /* dss_data4.dss_data4 */ + 0x0b6 (PIN_OUTPUT | MUX_MODE0) /* dss_data5.dss_data5 */ + 0x0b8 (PIN_OUTPUT | MUX_MODE0) /* dss_data6.dss_data6 */ + 0x0ba (PIN_OUTPUT | MUX_MODE0) /* dss_data7.dss_data7 */ + 0x0bc (PIN_OUTPUT | MUX_MODE0) /* dss_data8.dss_data8 */ + 0x0be (PIN_OUTPUT | MUX_MODE0) /* dss_data9.dss_data9 */ + 0x0c0 (PIN_OUTPUT | MUX_MODE0) /* dss_data10.dss_data10 */ + 0x0c2 (PIN_OUTPUT | MUX_MODE0) /* dss_data11.dss_data11 */ + 0x0c4 (PIN_OUTPUT | MUX_MODE0) /* dss_data12.dss_data12 */ + 0x0c6 (PIN_OUTPUT | MUX_MODE0) /* dss_data13.dss_data13 */ + 0x0c8 (PIN_OUTPUT | MUX_MODE0) /* dss_data14.dss_data14 */ + 0x0ca (PIN_OUTPUT | MUX_MODE0) /* dss_data15.dss_data15 */ + 0x0cc (PIN_OUTPUT | MUX_MODE0) /* dss_data16.dss_data16 */ + 0x0ce (PIN_OUTPUT | MUX_MODE0) /* dss_data17.dss_data17 */ + 0x0d0 (PIN_OUTPUT | MUX_MODE0) /* dss_data18.dss_data18 */ + 0x0d2 (PIN_OUTPUT | MUX_MODE0) /* dss_data19.dss_data19 */ + 0x0d4 (PIN_OUTPUT | MUX_MODE0) /* dss_data20.dss_data20 */ + 0x0d6 (PIN_OUTPUT | MUX_MODE0) /* dss_data21.dss_data21 */ + 0x0d8 (PIN_OUTPUT | MUX_MODE0) /* dss_data22.dss_data22 */ + 0x0da (PIN_OUTPUT | MUX_MODE0) /* dss_data23.dss_data23 */ + >; + }; }; &leds_pins { @@ -174,3 +215,8 @@ &usbhsehci { phys = <&hsusb1_phy>; }; + +&vpll2 { + /* Needed for DSS */ + regulator-name = "vdds_dsi"; +}; diff --git a/arch/arm/boot/dts/omap3-igep0030.dts b/arch/arm/boot/dts/omap3-igep0030.dts index 525e6d9b0978..02a23f8a3384 100644 --- a/arch/arm/boot/dts/omap3-igep0030.dts +++ b/arch/arm/boot/dts/omap3-igep0030.dts @@ -1,5 +1,5 @@ /* - * Device Tree Source for IGEP COM Module + * Device Tree Source for IGEP COM MODULE (TI OMAP AM/DM37x) * * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk> * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com> @@ -12,7 +12,7 @@ #include "omap3-igep.dtsi" / { - model = "IGEP COM Module"; + model = "IGEP COM MODULE (TI OMAP AM/DM37x)"; compatible = "isee,omap3-igep0030", "ti,omap3"; leds { diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts index c4f20bfe4cce..c2c306d13b87 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/omap3-n900.dts @@ -125,6 +125,21 @@ >; }; + mmc2_pins: pinmux_mmc2_pins { + pinctrl-single,pins = < + 0x128 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk */ + 0x12a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd */ + 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0 */ + 0x12e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1 */ + 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat2 */ + 0x132 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat3 */ + 0x134 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat4 */ + 0x136 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat5 */ + 0x138 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat6 */ + 0x13a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat7 */ + >; + }; + display_pins: pinmux_display_pins { pinctrl-single,pins = < 0x0d4 (PIN_OUTPUT | MUX_MODE4) /* RX51_LCD_RESET_GPIO */ @@ -358,8 +373,14 @@ cd-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* 160 */ }; +/* most boards use vaux3, only some old versions use vmmc2 instead */ &mmc2 { - status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <&vaux3>; + vmmc_aux-supply = <&vsim>; + bus-width = <8>; + non-removable; }; &mmc3 { diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index f3a0c26ed0c2..daabf99d402a 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -82,6 +82,13 @@ ranges; ti,hwmods = "l3_main"; + aes: aes@480c5000 { + compatible = "ti,omap3-aes"; + ti,hwmods = "aes"; + reg = <0x480c5000 0x50>; + interrupts = <0>; + }; + counter32k: counter@48320000 { compatible = "ti,omap-counter32k"; reg = <0x48320000 0x20>; @@ -260,6 +267,13 @@ ti,hwmods = "i2c3"; }; + mailbox: mailbox@48094000 { + compatible = "ti,omap3-mailbox"; + ti,hwmods = "mailbox"; + reg = <0x48094000 0x200>; + interrupts = <26>; + }; + mcspi1: spi@48098000 { compatible = "ti,omap2-mcspi"; reg = <0x48098000 0x100>; @@ -357,6 +371,13 @@ dma-names = "tx", "rx"; }; + mmu_isp: mmu@480bd400 { + compatible = "ti,omap3-mmu-isp"; + ti,hwmods = "mmu_isp"; + reg = <0x480bd400 0x80>; + interrupts = <8>; + }; + wdt2: wdt@48314000 { compatible = "ti,omap3-wdt"; reg = <0x48314000 0x80>; @@ -442,6 +463,27 @@ dma-names = "tx", "rx"; }; + sham: sham@480c3000 { + compatible = "ti,omap3-sham"; + ti,hwmods = "sham"; + reg = <0x480c3000 0x64>; + interrupts = <49>; + }; + + smartreflex_core: smartreflex@480cb000 { + compatible = "ti,omap3-smartreflex-core"; + ti,hwmods = "smartreflex_core"; + reg = <0x480cb000 0x400>; + interrupts = <19>; + }; + + smartreflex_mpu_iva: smartreflex@480c9000 { + compatible = "ti,omap3-smartreflex-iva"; + ti,hwmods = "smartreflex_mpu_iva"; + reg = <0x480c9000 0x400>; + interrupts = <18>; + }; + timer1: timer@48318000 { compatible = "ti,omap3430-timer"; reg = <0x48318000 0x400>; diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi index 298e85020e1b..88c6a05cab41 100644 --- a/arch/arm/boot/dts/omap4-panda-common.dtsi +++ b/arch/arm/boot/dts/omap4-panda-common.dtsi @@ -246,15 +246,6 @@ 0xf0 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */ >; }; -}; - -&omap4_pmx_wkup { - led_wkgpio_pins: pinmux_leds_wkpins { - pinctrl-single,pins = < - 0x1a (PIN_OUTPUT | MUX_MODE3) /* gpio_wk7 */ - 0x1c (PIN_OUTPUT | MUX_MODE3) /* gpio_wk8 */ - >; - }; /* * wl12xx GPIO outputs for WLAN_EN, BT_EN, FM_EN, BT_WAKEUP @@ -274,7 +265,7 @@ pinctrl-single,pins = < 0x38 (PIN_INPUT | MUX_MODE3) /* gpmc_ncs2.gpio_52 */ 0x3a (PIN_INPUT | MUX_MODE3) /* gpmc_ncs3.gpio_53 */ - 0x108 (PIN_OUTPUT | MUX_MODE0) /* sdmmc5_clk.sdmmc5_clk */ + 0x108 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_clk.sdmmc5_clk */ 0x10a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_cmd.sdmmc5_cmd */ 0x10c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_dat0.sdmmc5_dat0 */ 0x10e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_dat1.sdmmc5_dat1 */ @@ -284,6 +275,15 @@ }; }; +&omap4_pmx_wkup { + led_wkgpio_pins: pinmux_leds_wkpins { + pinctrl-single,pins = < + 0x1a (PIN_OUTPUT | MUX_MODE3) /* gpio_wk7 */ + 0x1c (PIN_OUTPUT | MUX_MODE3) /* gpio_wk8 */ + >; + }; +}; + &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins>; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 5fc3f43c5a81..dbc81fb6ef03 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -300,12 +300,12 @@ wl12xx_pins: pinmux_wl12xx_pins { pinctrl-single,pins = < 0x3a (PIN_INPUT | MUX_MODE3) /* gpmc_ncs3.gpio_53 */ - 0x108 (PIN_OUTPUT | MUX_MODE3) /* sdmmc5_clk.sdmmc5_clk */ - 0x10a (PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc5_cmd.sdmmc5_cmd */ - 0x10c (PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc5_dat0.sdmmc5_dat0 */ - 0x10e (PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc5_dat1.sdmmc5_dat1 */ - 0x110 (PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc5_dat2.sdmmc5_dat2 */ - 0x112 (PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc5_dat3.sdmmc5_dat3 */ + 0x108 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_clk.sdmmc5_clk */ + 0x10a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_cmd.sdmmc5_cmd */ + 0x10c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_dat0.sdmmc5_dat0 */ + 0x10e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_dat1.sdmmc5_dat1 */ + 0x110 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_dat2.sdmmc5_dat2 */ + 0x112 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_dat3.sdmmc5_dat3 */ >; }; }; diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 5cdaba4cea86..de9feced9935 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -13,6 +13,7 @@ #include <dt-bindings/pinctrl/at91.h> #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/clk/at91.h> / { model = "Atmel SAMA5D3 family SoC"; @@ -56,6 +57,14 @@ reg = <0x20000000 0x8000000>; }; + clocks { + adc_op_clk: adc_op_clk{ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <20000000>; + }; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; @@ -79,6 +88,8 @@ status = "disabled"; #address-cells = <1>; #size-cells = <0>; + clocks = <&mci0_clk>; + clock-names = "mci_clk"; }; spi0: spi@f0004000 { @@ -92,6 +103,8 @@ dma-names = "tx", "rx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi0>; + clocks = <&spi0_clk>; + clock-names = "spi_clk"; status = "disabled"; }; @@ -101,6 +114,8 @@ interrupts = <38 IRQ_TYPE_LEVEL_HIGH 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>; + clocks = <&ssc0_clk>; + clock-names = "pclk"; status = "disabled"; }; @@ -108,6 +123,8 @@ compatible = "atmel,at91sam9x5-tcb"; reg = <0xf0010000 0x100>; interrupts = <26 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&tcb0_clk>; + clock-names = "t0_clk"; }; i2c0: i2c@f0014000 { @@ -121,6 +138,7 @@ pinctrl-0 = <&pinctrl_i2c0>; #address-cells = <1>; #size-cells = <0>; + clocks = <&twi0_clk>; status = "disabled"; }; @@ -135,6 +153,7 @@ pinctrl-0 = <&pinctrl_i2c1>; #address-cells = <1>; #size-cells = <0>; + clocks = <&twi1_clk>; status = "disabled"; }; @@ -144,6 +163,8 @@ interrupts = <12 IRQ_TYPE_LEVEL_HIGH 5>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usart0>; + clocks = <&usart0_clk>; + clock-names = "usart"; status = "disabled"; }; @@ -153,6 +174,8 @@ interrupts = <13 IRQ_TYPE_LEVEL_HIGH 5>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usart1>; + clocks = <&usart1_clk>; + clock-names = "usart"; status = "disabled"; }; @@ -174,6 +197,8 @@ status = "disabled"; #address-cells = <1>; #size-cells = <0>; + clocks = <&mci1_clk>; + clock-names = "mci_clk"; }; spi1: spi@f8008000 { @@ -187,6 +212,8 @@ dma-names = "tx", "rx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi1>; + clocks = <&spi1_clk>; + clock-names = "spi_clk"; status = "disabled"; }; @@ -196,6 +223,8 @@ interrupts = <39 IRQ_TYPE_LEVEL_HIGH 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>; + clocks = <&ssc1_clk>; + clock-names = "pclk"; status = "disabled"; }; @@ -219,6 +248,9 @@ &pinctrl_adc0_ad10 &pinctrl_adc0_ad11 >; + clocks = <&adc_clk>, + <&adc_op_clk>; + clock-names = "adc_clk", "adc_op_clk"; atmel,adc-channel-base = <0x50>; atmel,adc-channels-used = <0xfff>; atmel,adc-drdy-mask = <0x1000000>; @@ -274,6 +306,7 @@ dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; + clocks = <&twi2_clk>; status = "disabled"; }; @@ -283,6 +316,8 @@ interrupts = <14 IRQ_TYPE_LEVEL_HIGH 5>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usart2>; + clocks = <&usart2_clk>; + clock-names = "usart"; status = "disabled"; }; @@ -292,6 +327,8 @@ interrupts = <15 IRQ_TYPE_LEVEL_HIGH 5>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usart3>; + clocks = <&usart3_clk>; + clock-names = "usart"; status = "disabled"; }; @@ -318,6 +355,8 @@ reg = <0xffffe600 0x200>; interrupts = <30 IRQ_TYPE_LEVEL_HIGH 0>; #dma-cells = <2>; + clocks = <&dma0_clk>; + clock-names = "dma_clk"; }; dma1: dma-controller@ffffe800 { @@ -325,6 +364,8 @@ reg = <0xffffe800 0x200>; interrupts = <31 IRQ_TYPE_LEVEL_HIGH 0>; #dma-cells = <2>; + clocks = <&dma1_clk>; + clock-names = "dma_clk"; }; ramc0: ramc@ffffea00 { @@ -338,6 +379,8 @@ interrupts = <2 IRQ_TYPE_LEVEL_HIGH 7>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_dbgu>; + clocks = <&dbgu_clk>; + clock-names = "usart"; status = "disabled"; }; @@ -626,6 +669,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; + clocks = <&pioA_clk>; }; pioB: gpio@fffff400 { @@ -636,6 +680,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; + clocks = <&pioB_clk>; }; pioC: gpio@fffff600 { @@ -646,6 +691,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; + clocks = <&pioC_clk>; }; pioD: gpio@fffff800 { @@ -656,6 +702,7 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; + clocks = <&pioD_clk>; }; pioE: gpio@fffffa00 { @@ -666,12 +713,334 @@ gpio-controller; interrupt-controller; #interrupt-cells = <2>; + clocks = <&pioE_clk>; }; }; pmc: pmc@fffffc00 { - compatible = "atmel,at91rm9200-pmc"; + compatible = "atmel,sama5d3-pmc"; reg = <0xfffffc00 0x120>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; + interrupt-controller; + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <1>; + + clk32k: slck { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + main: mainck { + compatible = "atmel,at91rm9200-clk-main"; + #clock-cells = <0>; + interrupt-parent = <&pmc>; + interrupts = <AT91_PMC_MOSCS>; + clocks = <&clk32k>; + }; + + plla: pllack { + compatible = "atmel,sama5d3-clk-pll"; + #clock-cells = <0>; + interrupt-parent = <&pmc>; + interrupts = <AT91_PMC_LOCKA>; + clocks = <&main>; + reg = <0>; + atmel,clk-input-range = <8000000 50000000>; + #atmel,pll-clk-output-range-cells = <4>; + atmel,pll-clk-output-ranges = <400000000 1000000000 0 0>; + }; + + plladiv: plladivck { + compatible = "atmel,at91sam9x5-clk-plldiv"; + #clock-cells = <0>; + clocks = <&plla>; + }; + + utmi: utmick { + compatible = "atmel,at91sam9x5-clk-utmi"; + #clock-cells = <0>; + interrupt-parent = <&pmc>; + interrupts = <AT91_PMC_LOCKU>; + clocks = <&main>; + }; + + mck: masterck { + compatible = "atmel,at91sam9x5-clk-master"; + #clock-cells = <0>; + interrupt-parent = <&pmc>; + interrupts = <AT91_PMC_MCKRDY>; + clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>; + atmel,clk-output-range = <0 166000000>; + atmel,clk-divisors = <1 2 4 3>; + }; + + usb: usbck { + compatible = "atmel,at91sam9x5-clk-usb"; + #clock-cells = <0>; + clocks = <&plladiv>, <&utmi>; + }; + + prog: progck { + compatible = "atmel,at91sam9x5-clk-programmable"; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&pmc>; + clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>; + + prog0: prog0 { + #clock-cells = <0>; + reg = <0>; + interrupts = <AT91_PMC_PCKRDY(0)>; + }; + + prog1: prog1 { + #clock-cells = <0>; + reg = <1>; + interrupts = <AT91_PMC_PCKRDY(1)>; + }; + + prog2: prog2 { + #clock-cells = <0>; + reg = <2>; + interrupts = <AT91_PMC_PCKRDY(2)>; + }; + }; + + smd: smdclk { + compatible = "atmel,at91sam9x5-clk-smd"; + #clock-cells = <0>; + clocks = <&plladiv>, <&utmi>; + }; + + systemck { + compatible = "atmel,at91rm9200-clk-system"; + #address-cells = <1>; + #size-cells = <0>; + + ddrck: ddrck { + #clock-cells = <0>; + reg = <2>; + clocks = <&mck>; + }; + + smdck: smdck { + #clock-cells = <0>; + reg = <4>; + clocks = <&smd>; + }; + + uhpck: uhpck { + #clock-cells = <0>; + reg = <6>; + clocks = <&usb>; + }; + + udpck: udpck { + #clock-cells = <0>; + reg = <7>; + clocks = <&usb>; + }; + + pck0: pck0 { + #clock-cells = <0>; + reg = <8>; + clocks = <&prog0>; + }; + + pck1: pck1 { + #clock-cells = <0>; + reg = <9>; + clocks = <&prog1>; + }; + + pck2: pck2 { + #clock-cells = <0>; + reg = <10>; + clocks = <&prog2>; + }; + }; + + periphck { + compatible = "atmel,at91sam9x5-clk-peripheral"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&mck>; + + dbgu_clk: dbgu_clk { + #clock-cells = <0>; + reg = <2>; + }; + + pioA_clk: pioA_clk { + #clock-cells = <0>; + reg = <6>; + }; + + pioB_clk: pioB_clk { + #clock-cells = <0>; + reg = <7>; + }; + + pioC_clk: pioC_clk { + #clock-cells = <0>; + reg = <8>; + }; + + pioD_clk: pioD_clk { + #clock-cells = <0>; + reg = <9>; + }; + + pioE_clk: pioE_clk { + #clock-cells = <0>; + reg = <10>; + }; + + usart0_clk: usart0_clk { + #clock-cells = <0>; + reg = <12>; + atmel,clk-output-range = <0 66000000>; + }; + + usart1_clk: usart1_clk { + #clock-cells = <0>; + reg = <13>; + atmel,clk-output-range = <0 66000000>; + }; + + usart2_clk: usart2_clk { + #clock-cells = <0>; + reg = <14>; + atmel,clk-output-range = <0 66000000>; + }; + + usart3_clk: usart3_clk { + #clock-cells = <0>; + reg = <15>; + atmel,clk-output-range = <0 66000000>; + }; + + twi0_clk: twi0_clk { + reg = <18>; + #clock-cells = <0>; + atmel,clk-output-range = <0 16625000>; + }; + + twi1_clk: twi1_clk { + #clock-cells = <0>; + reg = <19>; + atmel,clk-output-range = <0 16625000>; + }; + + twi2_clk: twi2_clk { + #clock-cells = <0>; + reg = <20>; + atmel,clk-output-range = <0 16625000>; + }; + + mci0_clk: mci0_clk { + #clock-cells = <0>; + reg = <21>; + }; + + mci1_clk: mci1_clk { + #clock-cells = <0>; + reg = <22>; + }; + + spi0_clk: spi0_clk { + #clock-cells = <0>; + reg = <24>; + atmel,clk-output-range = <0 133000000>; + }; + + spi1_clk: spi1_clk { + #clock-cells = <0>; + reg = <25>; + atmel,clk-output-range = <0 133000000>; + }; + + tcb0_clk: tcb0_clk { + #clock-cells = <0>; + reg = <26>; + atmel,clk-output-range = <0 133000000>; + }; + + pwm_clk: pwm_clk { + #clock-cells = <0>; + reg = <28>; + }; + + adc_clk: adc_clk { + #clock-cells = <0>; + reg = <29>; + atmel,clk-output-range = <0 66000000>; + }; + + dma0_clk: dma0_clk { + #clock-cells = <0>; + reg = <30>; + }; + + dma1_clk: dma1_clk { + #clock-cells = <0>; + reg = <31>; + }; + + uhphs_clk: uhphs_clk { + #clock-cells = <0>; + reg = <32>; + }; + + udphs_clk: udphs_clk { + #clock-cells = <0>; + reg = <33>; + }; + + isi_clk: isi_clk { + #clock-cells = <0>; + reg = <37>; + }; + + ssc0_clk: ssc0_clk { + #clock-cells = <0>; + reg = <38>; + atmel,clk-output-range = <0 66000000>; + }; + + ssc1_clk: ssc1_clk { + #clock-cells = <0>; + reg = <39>; + atmel,clk-output-range = <0 66000000>; + }; + + sha_clk: sha_clk { + #clock-cells = <0>; + reg = <42>; + }; + + aes_clk: aes_clk { + #clock-cells = <0>; + reg = <43>; + }; + + tdes_clk: tdes_clk { + #clock-cells = <0>; + reg = <44>; + }; + + trng_clk: trng_clk { + #clock-cells = <0>; + reg = <45>; + }; + + fuse_clk: fuse_clk { + #clock-cells = <0>; + reg = <48>; + }; + }; }; rstc@fffffe00 { @@ -683,6 +1052,7 @@ compatible = "atmel,at91sam9260-pit"; reg = <0xfffffe30 0xf>; interrupts = <3 IRQ_TYPE_LEVEL_HIGH 5>; + clocks = <&mck>; }; watchdog@fffffe40 { @@ -705,6 +1075,8 @@ reg = <0x00500000 0x100000 0xf8030000 0x4000>; interrupts = <33 IRQ_TYPE_LEVEL_HIGH 2>; + clocks = <&udphs_clk>, <&utmi>; + clock-names = "pclk", "hclk"; status = "disabled"; ep0 { @@ -817,6 +1189,9 @@ compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00600000 0x100000>; interrupts = <32 IRQ_TYPE_LEVEL_HIGH 2>; + clocks = <&usb>, <&uhphs_clk>, <&udphs_clk>, + <&uhpck>; + clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck"; status = "disabled"; }; @@ -824,6 +1199,8 @@ compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; reg = <0x00700000 0x100000>; interrupts = <32 IRQ_TYPE_LEVEL_HIGH 2>; + clocks = <&usb>, <&uhphs_clk>, <&uhpck>; + clock-names = "usb_clk", "ehci_clk", "uhpck"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/sama5d3_can.dtsi b/arch/arm/boot/dts/sama5d3_can.dtsi index 8ed3260cef66..a0775851cce5 100644 --- a/arch/arm/boot/dts/sama5d3_can.dtsi +++ b/arch/arm/boot/dts/sama5d3_can.dtsi @@ -32,12 +32,30 @@ }; + pmc: pmc@fffffc00 { + periphck { + can0_clk: can0_clk { + #clock-cells = <0>; + reg = <40>; + atmel,clk-output-range = <0 66000000>; + }; + + can1_clk: can0_clk { + #clock-cells = <0>; + reg = <41>; + atmel,clk-output-range = <0 66000000>; + }; + }; + }; + can0: can@f000c000 { compatible = "atmel,at91sam9x5-can"; reg = <0xf000c000 0x300>; interrupts = <40 IRQ_TYPE_LEVEL_HIGH 3>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can0_rx_tx>; + clocks = <&can0_clk>; + clock-names = "can_clk"; status = "disabled"; }; @@ -47,6 +65,8 @@ interrupts = <41 IRQ_TYPE_LEVEL_HIGH 3>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can1_rx_tx>; + clocks = <&can1_clk>; + clock-names = "can_clk"; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/sama5d3_emac.dtsi b/arch/arm/boot/dts/sama5d3_emac.dtsi index 4d4f351f1f9f..fe2af9276312 100644 --- a/arch/arm/boot/dts/sama5d3_emac.dtsi +++ b/arch/arm/boot/dts/sama5d3_emac.dtsi @@ -31,12 +31,23 @@ }; }; + pmc: pmc@fffffc00 { + periphck { + macb1_clk: macb1_clk { + #clock-cells = <0>; + reg = <35>; + }; + }; + }; + macb1: ethernet@f802c000 { compatible = "cdns,at32ap7000-macb", "cdns,macb"; reg = <0xf802c000 0x100>; interrupts = <35 IRQ_TYPE_LEVEL_HIGH 3>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_macb1_rmii>; + clocks = <&macb1_clk>, <&macb1_clk>; + clock-names = "hclk", "pclk"; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/sama5d3_gmac.dtsi b/arch/arm/boot/dts/sama5d3_gmac.dtsi index 0ba8be30ccd8..a6cb0508762f 100644 --- a/arch/arm/boot/dts/sama5d3_gmac.dtsi +++ b/arch/arm/boot/dts/sama5d3_gmac.dtsi @@ -64,12 +64,23 @@ }; }; + pmc: pmc@fffffc00 { + periphck { + macb0_clk: macb0_clk { + #clock-cells = <0>; + reg = <34>; + }; + }; + }; + macb0: ethernet@f0028000 { compatible = "cdns,pc302-gem", "cdns,gem"; reg = <0xf0028000 0x100>; interrupts = <34 IRQ_TYPE_LEVEL_HIGH 3>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_macb0_data_rgmii &pinctrl_macb0_signal_rgmii>; + clocks = <&macb0_clk>, <&macb0_clk>; + clock-names = "hclk", "pclk"; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/sama5d3_lcd.dtsi b/arch/arm/boot/dts/sama5d3_lcd.dtsi index 01f52a79f8ba..85d302701565 100644 --- a/arch/arm/boot/dts/sama5d3_lcd.dtsi +++ b/arch/arm/boot/dts/sama5d3_lcd.dtsi @@ -50,6 +50,23 @@ }; }; }; + + pmc: pmc@fffffc00 { + periphck { + lcdc_clk: lcdc_clk { + #clock-cells = <0>; + reg = <36>; + }; + }; + + systemck { + lcdck: lcdck { + #clock-cells = <0>; + reg = <3>; + clocks = <&mck>; + }; + }; + }; }; }; }; diff --git a/arch/arm/boot/dts/sama5d3_mci2.dtsi b/arch/arm/boot/dts/sama5d3_mci2.dtsi index 38e88e39e551..b029fe7ef17a 100644 --- a/arch/arm/boot/dts/sama5d3_mci2.dtsi +++ b/arch/arm/boot/dts/sama5d3_mci2.dtsi @@ -9,6 +9,7 @@ #include <dt-bindings/pinctrl/at91.h> #include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/clk/at91.h> / { ahb { @@ -30,6 +31,15 @@ }; }; + pmc: pmc@fffffc00 { + periphck { + mci2_clk: mci2_clk { + #clock-cells = <0>; + reg = <23>; + }; + }; + }; + mmc2: mmc@f8004000 { compatible = "atmel,hsmci"; reg = <0xf8004000 0x600>; @@ -38,6 +48,8 @@ dma-names = "rxtx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mmc2_clk_cmd_dat0 &pinctrl_mmc2_dat1_3>; + clocks = <&mci2_clk>; + clock-names = "mci_clk"; status = "disabled"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/sama5d3_tcb1.dtsi index 5264bb4a6998..382b04431f66 100644 --- a/arch/arm/boot/dts/sama5d3_tcb1.dtsi +++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi @@ -9,6 +9,7 @@ #include <dt-bindings/pinctrl/at91.h> #include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/clk/at91.h> / { aliases { @@ -17,10 +18,21 @@ ahb { apb { + pmc: pmc@fffffc00 { + periphck { + tcb1_clk: tcb1_clk { + #clock-cells = <0>; + reg = <27>; + }; + }; + }; + tcb1: timer@f8014000 { compatible = "atmel,at91sam9x5-tcb"; reg = <0xf8014000 0x100>; interrupts = <27 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&tcb1_clk>; + clock-names = "t0_clk"; }; }; }; diff --git a/arch/arm/boot/dts/sama5d3_uart.dtsi b/arch/arm/boot/dts/sama5d3_uart.dtsi index 98fcb2d57446..49d4d76ca6f4 100644 --- a/arch/arm/boot/dts/sama5d3_uart.dtsi +++ b/arch/arm/boot/dts/sama5d3_uart.dtsi @@ -9,6 +9,7 @@ #include <dt-bindings/pinctrl/at91.h> #include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/clk/at91.h> / { ahb { @@ -31,12 +32,30 @@ }; }; + pmc: pmc@fffffc00 { + periphck { + uart0_clk: uart0_clk { + #clock-cells = <0>; + reg = <16>; + atmel,clk-output-range = <0 66000000>; + }; + + uart1_clk: uart1_clk { + #clock-cells = <0>; + reg = <17>; + atmel,clk-output-range = <0 66000000>; + }; + }; + }; + uart0: serial@f0024000 { compatible = "atmel,at91sam9260-usart"; reg = <0xf0024000 0x200>; interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart0>; + clocks = <&uart0_clk>; + clock-names = "usart"; status = "disabled"; }; @@ -46,6 +65,8 @@ interrupts = <17 IRQ_TYPE_LEVEL_HIGH 5>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; + clocks = <&uart1_clk>; + clock-names = "usart"; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi index 726a0f35100c..f55ed072c8e6 100644 --- a/arch/arm/boot/dts/sama5d3xcm.dtsi +++ b/arch/arm/boot/dts/sama5d3xcm.dtsi @@ -18,17 +18,6 @@ reg = <0x20000000 0x20000000>; }; - clocks { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - main_clock: clock@0 { - compatible = "atmel,osc", "fixed-clock"; - clock-frequency = <12000000>; - }; - }; - ahb { apb { spi0: spi@f0004000 { @@ -38,6 +27,12 @@ macb0: ethernet@f0028000 { phy-mode = "rgmii"; }; + + pmc: pmc@fffffc00 { + main: mainck { + clock-frequency = <12000000>; + }; + }; }; nand0: nand@60000000 { diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index 6d09b8d42fdd..f936476c2753 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -245,14 +245,14 @@ mpu_periph_clk: mpu_periph_clk { #clock-cells = <0>; - compatible = "altr,socfpga-gate-clk"; + compatible = "altr,socfpga-perip-clk"; clocks = <&mpuclk>; fixed-divider = <4>; }; mpu_l2_ram_clk: mpu_l2_ram_clk { #clock-cells = <0>; - compatible = "altr,socfpga-gate-clk"; + compatible = "altr,socfpga-perip-clk"; clocks = <&mpuclk>; fixed-divider = <2>; }; @@ -266,8 +266,9 @@ l3_main_clk: l3_main_clk { #clock-cells = <0>; - compatible = "altr,socfpga-gate-clk"; + compatible = "altr,socfpga-perip-clk"; clocks = <&mainclk>; + fixed-divider = <1>; }; l3_mp_clk: l3_mp_clk { diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 4a5903e04827..c1df4e9db140 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -69,6 +69,7 @@ CONFIG_KS8851=y CONFIG_SMSC911X=y CONFIG_STMMAC_ETH=y CONFIG_MDIO_SUN4I=y +CONFIG_TI_CPSW=y CONFIG_KEYBOARD_SPEAR=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_8250=y @@ -133,12 +134,14 @@ CONFIG_USB_GPIO_VBUS=y CONFIG_USB_ISP1301=y CONFIG_USB_MXS_PHY=y CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=16 CONFIG_MMC_ARMMMCI=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_ESDHC_IMX=y CONFIG_MMC_SDHCI_TEGRA=y CONFIG_MMC_SDHCI_SPEAR=y +CONFIG_MMC_SDHCI_BCM_KONA=y CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y CONFIG_EDAC=y diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 98a50c309b90..bfa80a11e8c7 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -173,6 +173,7 @@ CONFIG_MFD_PALMAS=y CONFIG_MFD_TPS65217=y CONFIG_MFD_TPS65910=y CONFIG_TWL6040_CORE=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_PALMAS=y CONFIG_REGULATOR_TPS65023=y CONFIG_REGULATOR_TPS6507X=y diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index d57a85badb5e..3e2259b60236 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -12,6 +12,9 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set @@ -58,4 +61,8 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_COMMON_CLK_DEBUG=y # CONFIG_IOMMU_SUPPORT is not set +CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y CONFIG_NLS=y +CONFIG_PRINTK_TIME=y diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index ac632cc38f24..c6ebc184bf68 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -22,6 +22,7 @@ CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8" CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_CPU_IDLE=y +CONFIG_ARM_U8500_CPUIDLE=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_PM_RUNTIME=y @@ -109,6 +110,8 @@ CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=y CONFIG_EXT4_FS=y CONFIG_VFAT_FS=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y # CONFIG_MISC_FILESYSTEMS is not set diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 699b71e7f7ec..b4f7d6ffa30b 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -1,15 +1,33 @@ if ARCH_AT91 +config HAVE_AT91_UTMI + bool + +config HAVE_AT91_USB_CLK + bool + config HAVE_AT91_DBGU0 bool config HAVE_AT91_DBGU1 bool +config AT91_USE_OLD_CLK + bool + config AT91_PMC_UNIT bool default !ARCH_AT91X40 +config COMMON_CLK_AT91 + bool + default AT91_PMC_UNIT && USE_OF && !AT91_USE_OLD_CLK + select COMMON_CLK + +config OLD_CLK_AT91 + bool + default AT91_PMC_UNIT && AT91_USE_OLD_CLK + config AT91_SAM9_ALT_RESET bool default !ARCH_AT91X40 @@ -21,6 +39,9 @@ config AT91_SAM9G45_RESET config AT91_SAM9_TIME bool +config HAVE_AT91_SMD + bool + config SOC_AT91SAM9 bool select AT91_SAM9_TIME @@ -65,6 +86,9 @@ config SOC_SAMA5D3 select SOC_SAMA5 select HAVE_FB_ATMEL select HAVE_AT91_DBGU1 + select HAVE_AT91_UTMI + select HAVE_AT91_SMD + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's SAMA5D3 family SoC. This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. @@ -78,11 +102,15 @@ config SOC_AT91RM9200 select HAVE_AT91_DBGU0 select MULTI_IRQ_HANDLER select SPARSE_IRQ + select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9260 bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20" select HAVE_AT91_DBGU0 select SOC_AT91SAM9 + select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE or AT91SAM9G20 SoC. @@ -92,6 +120,8 @@ config SOC_AT91SAM9261 select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. @@ -100,18 +130,25 @@ config SOC_AT91SAM9263 select HAVE_AT91_DBGU1 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK config SOC_AT91SAM9RL bool "AT91SAM9RL" select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI config SOC_AT91SAM9G45 bool "AT91SAM9G45 or AT91SAM9M10 families" select HAVE_AT91_DBGU1 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -121,6 +158,10 @@ config SOC_AT91SAM9X5 select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK + select HAVE_AT91_UTMI + select HAVE_AT91_SMD + select HAVE_AT91_USB_CLK help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is @@ -133,6 +174,8 @@ config SOC_AT91SAM9N12 select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL select SOC_AT91SAM9 + select AT91_USE_OLD_CLK + select HAVE_AT91_USB_CLK help Select this if you are using Atmel's AT91SAM9N12 SoC. diff --git a/arch/arm/mach-at91/Kconfig.non_dt b/arch/arm/mach-at91/Kconfig.non_dt index ca900be144ce..b736b571e882 100644 --- a/arch/arm/mach-at91/Kconfig.non_dt +++ b/arch/arm/mach-at91/Kconfig.non_dt @@ -12,26 +12,32 @@ config ARCH_AT91_NONE config ARCH_AT91RM9200 bool "AT91RM9200" select SOC_AT91RM9200 + select AT91_USE_OLD_CLK config ARCH_AT91SAM9260 bool "AT91SAM9260 or AT91SAM9XE or AT91SAM9G20" select SOC_AT91SAM9260 + select AT91_USE_OLD_CLK config ARCH_AT91SAM9261 bool "AT91SAM9261 or AT91SAM9G10" select SOC_AT91SAM9261 + select AT91_USE_OLD_CLK config ARCH_AT91SAM9263 bool "AT91SAM9263" select SOC_AT91SAM9263 + select AT91_USE_OLD_CLK config ARCH_AT91SAM9RL bool "AT91SAM9RL" select SOC_AT91SAM9RL + select AT91_USE_OLD_CLK config ARCH_AT91SAM9G45 bool "AT91SAM9G45" select SOC_AT91SAM9G45 + select AT91_USE_OLD_CLK config ARCH_AT91X40 bool "AT91x40" diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 90aab2d5a07f..705b38a179ec 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -7,7 +7,7 @@ obj-m := obj-n := obj- := -obj-$(CONFIG_AT91_PMC_UNIT) += clock.o +obj-$(CONFIG_OLD_CLK_AT91) += clock.o obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o obj-$(CONFIG_AT91_SAM9_TIME) += at91sam926x_time.o diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index 25805f2f6010..e47f5fd232f5 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -12,13 +12,13 @@ #include <linux/module.h> #include <linux/reboot.h> +#include <linux/clk/at91_pmc.h> #include <asm/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/system_misc.h> #include <mach/at91rm9200.h> -#include <mach/at91_pmc.h> #include <mach/at91_st.h> #include <mach/cpu.h> diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index d6a1fa85371d..6c821e562159 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -11,6 +11,7 @@ */ #include <linux/module.h> +#include <linux/clk/at91_pmc.h> #include <asm/proc-fns.h> #include <asm/irq.h> @@ -20,7 +21,6 @@ #include <mach/cpu.h> #include <mach/at91_dbgu.h> #include <mach/at91sam9260.h> -#include <mach/at91_pmc.h> #include "at91_aic.h" #include "at91_rstc.h" diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 23ba1d8a1531..6276b4c1acfe 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -11,6 +11,7 @@ */ #include <linux/module.h> +#include <linux/clk/at91_pmc.h> #include <asm/proc-fns.h> #include <asm/irq.h> @@ -19,7 +20,6 @@ #include <asm/system_misc.h> #include <mach/cpu.h> #include <mach/at91sam9261.h> -#include <mach/at91_pmc.h> #include "at91_aic.h" #include "at91_rstc.h" diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 7eccb0fc57bc..37b90f4b990c 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -11,6 +11,7 @@ */ #include <linux/module.h> +#include <linux/clk/at91_pmc.h> #include <asm/proc-fns.h> #include <asm/irq.h> @@ -18,7 +19,6 @@ #include <asm/mach/map.h> #include <asm/system_misc.h> #include <mach/at91sam9263.h> -#include <mach/at91_pmc.h> #include "at91_aic.h" #include "at91_rstc.h" diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index bb392320a0dd..0f04ffe9c5a8 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c @@ -39,6 +39,7 @@ static u32 pit_cycle; /* write-once */ static u32 pit_cnt; /* access only w/system irq blocked */ static void __iomem *pit_base_addr __read_mostly; +static struct clk *mck; static inline unsigned int pit_read(unsigned int reg_offset) { @@ -195,10 +196,14 @@ static int __init of_at91sam926x_pit_init(void) if (!pit_base_addr) goto node_err; + mck = of_clk_get(np, 0); + /* Get the interrupts property */ ret = irq_of_parse_and_map(np, 0); if (!ret) { pr_crit("AT91: PIT: Unable to get IRQ from DT\n"); + if (!IS_ERR(mck)) + clk_put(mck); goto ioremap_err; } at91sam926x_pit_irq.irq = ret; @@ -230,6 +235,8 @@ void __init at91sam926x_pit_init(void) unsigned bits; int ret; + mck = ERR_PTR(-ENOENT); + /* For device tree enabled device: initialize here */ of_at91sam926x_pit_init(); @@ -237,7 +244,12 @@ void __init at91sam926x_pit_init(void) * Use our actual MCK to figure out how many MCK/16 ticks per * 1/HZ period (instead of a compile-time constant LATCH). */ - pit_rate = clk_get_rate(clk_get(NULL, "mck")) / 16; + if (IS_ERR(mck)) + mck = clk_get(NULL, "mck"); + + if (IS_ERR(mck)) + panic("AT91: PIT: Unable to get mck clk\n"); + pit_rate = clk_get_rate(mck) / 16; pit_cycle = (pit_rate + HZ/2) / HZ; WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0); diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 9405aa08b104..2f455ce35268 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -12,13 +12,13 @@ #include <linux/module.h> #include <linux/dma-mapping.h> +#include <linux/clk/at91_pmc.h> #include <asm/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/system_misc.h> #include <mach/at91sam9g45.h> -#include <mach/at91_pmc.h> #include <mach/cpu.h> #include "at91_aic.h" diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c index 388ec3aec4b9..4ef088c62eab 100644 --- a/arch/arm/mach-at91/at91sam9n12.c +++ b/arch/arm/mach-at91/at91sam9n12.c @@ -8,12 +8,12 @@ #include <linux/module.h> #include <linux/dma-mapping.h> +#include <linux/clk/at91_pmc.h> #include <asm/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <mach/at91sam9n12.h> -#include <mach/at91_pmc.h> #include <mach/cpu.h> #include "board.h" diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index 0750ffb7e6b1..3651517abedf 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -10,6 +10,7 @@ */ #include <linux/module.h> +#include <linux/clk/at91_pmc.h> #include <asm/proc-fns.h> #include <asm/irq.h> @@ -19,7 +20,6 @@ #include <mach/cpu.h> #include <mach/at91_dbgu.h> #include <mach/at91sam9rl.h> -#include <mach/at91_pmc.h> #include "at91_aic.h" #include "at91_rstc.h" diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index e8a2e075a1b8..3e8ec26e39dc 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -8,12 +8,12 @@ #include <linux/module.h> #include <linux/dma-mapping.h> +#include <linux/clk/at91_pmc.h> #include <asm/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <mach/at91sam9x5.h> -#include <mach/at91_pmc.h> #include <mach/cpu.h> #include "board.h" diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/board-dt-sama5.c index bf00d15d954d..075ec0576ada 100644 --- a/arch/arm/mach-at91/board-dt-sama5.c +++ b/arch/arm/mach-at91/board-dt-sama5.c @@ -16,6 +16,7 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/phy.h> +#include <linux/clk-provider.h> #include <asm/setup.h> #include <asm/irq.h> @@ -26,6 +27,13 @@ #include "at91_aic.h" #include "generic.h" +static void __init sama5_dt_timer_init(void) +{ +#if defined(CONFIG_COMMON_CLK) + of_clk_init(NULL); +#endif + at91sam926x_pit_init(); +} static const struct of_device_id irq_of_match[] __initconst = { @@ -72,7 +80,7 @@ static const char *sama5_dt_board_compat[] __initdata = { DT_MACHINE_START(sama5_dt, "Atmel SAMA5 (Device Tree)") /* Maintainer: Atmel */ - .init_time = at91sam926x_pit_init, + .init_time = sama5_dt_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic5_handle_irq, .init_early = at91_dt_initialize, diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 6b2630a92f71..72b257944733 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -24,9 +24,9 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/of_address.h> +#include <linux/clk/at91_pmc.h> #include <mach/hardware.h> -#include <mach/at91_pmc.h> #include <mach/cpu.h> #include <asm/proc-fns.h> @@ -884,6 +884,11 @@ static int __init at91_pmc_init(unsigned long main_clock) #if defined(CONFIG_OF) static struct of_device_id pmc_ids[] = { { .compatible = "atmel,at91rm9200-pmc" }, + { .compatible = "atmel,at91sam9260-pmc" }, + { .compatible = "atmel,at91sam9g45-pmc" }, + { .compatible = "atmel,at91sam9n12-pmc" }, + { .compatible = "atmel,at91sam9x5-pmc" }, + { .compatible = "atmel,sama5d3-pmc" }, { /*sentinel*/ } }; diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 26dee3ce9397..631fa3b8c16d 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -46,11 +46,12 @@ extern void at91sam926x_pit_init(void); extern void at91x40_timer_init(void); /* Clocks */ -#ifdef CONFIG_AT91_PMC_UNIT +#ifdef CONFIG_OLD_CLK_AT91 extern int __init at91_clock_init(unsigned long main_clock); extern int __init at91_dt_clock_init(void); #else static int inline at91_clock_init(unsigned long main_clock) { return 0; } +static int inline at91_dt_clock_init(void) { return 0; } #endif struct device; diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 9986542e8060..d43b79f56e94 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -19,13 +19,13 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/clk/at91_pmc.h> #include <asm/irq.h> #include <linux/atomic.h> #include <asm/mach/time.h> #include <asm/mach/irq.h> -#include <mach/at91_pmc.h> #include <mach/cpu.h> #include "at91_aic.h" diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 3ed190ce062b..c5101dcb4fb0 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -16,7 +16,11 @@ #include <mach/at91_ramc.h> #include <mach/at91rm9200_sdramc.h> +#ifdef CONFIG_PM extern void at91_pm_set_standby(void (*at91_standby)(void)); +#else +static inline void at91_pm_set_standby(void (*at91_standby)(void)) { } +#endif /* * The AT91RM9200 goes into self-refresh mode with this command, and will diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index 098c28ddf025..20018779bae7 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S @@ -13,8 +13,8 @@ */ #include <linux/linkage.h> +#include <linux/clk/at91_pmc.h> #include <mach/hardware.h> -#include <mach/at91_pmc.h> #include <mach/at91_ramc.h> diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c index 3ea86428ee09..3d775d08de08 100644 --- a/arch/arm/mach-at91/sama5d3.c +++ b/arch/arm/mach-at91/sama5d3.c @@ -9,360 +9,19 @@ #include <linux/module.h> #include <linux/dma-mapping.h> +#include <linux/clk/at91_pmc.h> #include <asm/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <mach/sama5d3.h> -#include <mach/at91_pmc.h> #include <mach/cpu.h> #include "soc.h" #include "generic.h" -#include "clock.h" #include "sam9_smc.h" /* -------------------------------------------------------------------- - * Clocks - * -------------------------------------------------------------------- */ - -/* - * The peripheral clocks. - */ - -static struct clk pioA_clk = { - .name = "pioA_clk", - .pid = SAMA5D3_ID_PIOA, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk pioB_clk = { - .name = "pioB_clk", - .pid = SAMA5D3_ID_PIOB, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk pioC_clk = { - .name = "pioC_clk", - .pid = SAMA5D3_ID_PIOC, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk pioD_clk = { - .name = "pioD_clk", - .pid = SAMA5D3_ID_PIOD, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk pioE_clk = { - .name = "pioE_clk", - .pid = SAMA5D3_ID_PIOE, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk usart0_clk = { - .name = "usart0_clk", - .pid = SAMA5D3_ID_USART0, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk usart1_clk = { - .name = "usart1_clk", - .pid = SAMA5D3_ID_USART1, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk usart2_clk = { - .name = "usart2_clk", - .pid = SAMA5D3_ID_USART2, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk usart3_clk = { - .name = "usart3_clk", - .pid = SAMA5D3_ID_USART3, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk uart0_clk = { - .name = "uart0_clk", - .pid = SAMA5D3_ID_UART0, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk uart1_clk = { - .name = "uart1_clk", - .pid = SAMA5D3_ID_UART1, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk twi0_clk = { - .name = "twi0_clk", - .pid = SAMA5D3_ID_TWI0, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk twi1_clk = { - .name = "twi1_clk", - .pid = SAMA5D3_ID_TWI1, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk twi2_clk = { - .name = "twi2_clk", - .pid = SAMA5D3_ID_TWI2, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk mmc0_clk = { - .name = "mci0_clk", - .pid = SAMA5D3_ID_HSMCI0, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk mmc1_clk = { - .name = "mci1_clk", - .pid = SAMA5D3_ID_HSMCI1, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk mmc2_clk = { - .name = "mci2_clk", - .pid = SAMA5D3_ID_HSMCI2, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk spi0_clk = { - .name = "spi0_clk", - .pid = SAMA5D3_ID_SPI0, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk spi1_clk = { - .name = "spi1_clk", - .pid = SAMA5D3_ID_SPI1, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk tcb0_clk = { - .name = "tcb0_clk", - .pid = SAMA5D3_ID_TC0, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk tcb1_clk = { - .name = "tcb1_clk", - .pid = SAMA5D3_ID_TC1, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk adc_clk = { - .name = "adc_clk", - .pid = SAMA5D3_ID_ADC, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk adc_op_clk = { - .name = "adc_op_clk", - .type = CLK_TYPE_PERIPHERAL, - .rate_hz = 5000000, -}; -static struct clk dma0_clk = { - .name = "dma0_clk", - .pid = SAMA5D3_ID_DMA0, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk dma1_clk = { - .name = "dma1_clk", - .pid = SAMA5D3_ID_DMA1, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk uhphs_clk = { - .name = "uhphs", - .pid = SAMA5D3_ID_UHPHS, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk udphs_clk = { - .name = "udphs_clk", - .pid = SAMA5D3_ID_UDPHS, - .type = CLK_TYPE_PERIPHERAL, -}; -/* gmac only for sama5d33, sama5d34, sama5d35 */ -static struct clk macb0_clk = { - .name = "macb0_clk", - .pid = SAMA5D3_ID_GMAC, - .type = CLK_TYPE_PERIPHERAL, -}; -/* emac only for sama5d31, sama5d35 */ -static struct clk macb1_clk = { - .name = "macb1_clk", - .pid = SAMA5D3_ID_EMAC, - .type = CLK_TYPE_PERIPHERAL, -}; -/* lcd only for sama5d31, sama5d33, sama5d34 */ -static struct clk lcdc_clk = { - .name = "lcdc_clk", - .pid = SAMA5D3_ID_LCDC, - .type = CLK_TYPE_PERIPHERAL, -}; -/* isi only for sama5d33, sama5d35 */ -static struct clk isi_clk = { - .name = "isi_clk", - .pid = SAMA5D3_ID_ISI, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk can0_clk = { - .name = "can0_clk", - .pid = SAMA5D3_ID_CAN0, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk can1_clk = { - .name = "can1_clk", - .pid = SAMA5D3_ID_CAN1, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk ssc0_clk = { - .name = "ssc0_clk", - .pid = SAMA5D3_ID_SSC0, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk ssc1_clk = { - .name = "ssc1_clk", - .pid = SAMA5D3_ID_SSC1, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV2, -}; -static struct clk sha_clk = { - .name = "sha_clk", - .pid = SAMA5D3_ID_SHA, - .type = CLK_TYPE_PERIPHERAL, - .div = AT91_PMC_PCR_DIV8, -}; -static struct clk aes_clk = { - .name = "aes_clk", - .pid = SAMA5D3_ID_AES, - .type = CLK_TYPE_PERIPHERAL, -}; -static struct clk tdes_clk = { - .name = "tdes_clk", - .pid = SAMA5D3_ID_TDES, - .type = CLK_TYPE_PERIPHERAL, -}; - -static struct clk *periph_clocks[] __initdata = { - &pioA_clk, - &pioB_clk, - &pioC_clk, - &pioD_clk, - &pioE_clk, - &usart0_clk, - &usart1_clk, - &usart2_clk, - &usart3_clk, - &uart0_clk, - &uart1_clk, - &twi0_clk, - &twi1_clk, - &twi2_clk, - &mmc0_clk, - &mmc1_clk, - &mmc2_clk, - &spi0_clk, - &spi1_clk, - &tcb0_clk, - &tcb1_clk, - &adc_clk, - &adc_op_clk, - &dma0_clk, - &dma1_clk, - &uhphs_clk, - &udphs_clk, - &macb0_clk, - &macb1_clk, - &lcdc_clk, - &isi_clk, - &can0_clk, - &can1_clk, - &ssc0_clk, - &ssc1_clk, - &sha_clk, - &aes_clk, - &tdes_clk, -}; - -static struct clk pck0 = { - .name = "pck0", - .pmc_mask = AT91_PMC_PCK0, - .type = CLK_TYPE_PROGRAMMABLE, - .id = 0, -}; - -static struct clk pck1 = { - .name = "pck1", - .pmc_mask = AT91_PMC_PCK1, - .type = CLK_TYPE_PROGRAMMABLE, - .id = 1, -}; - -static struct clk pck2 = { - .name = "pck2", - .pmc_mask = AT91_PMC_PCK2, - .type = CLK_TYPE_PROGRAMMABLE, - .id = 2, -}; - -static struct clk_lookup periph_clocks_lookups[] = { - /* lookup table for DT entries */ - CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck), - 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", &pioD_clk), - CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioE_clk), - CLKDEV_CON_DEV_ID("usart", "f001c000.serial", &usart0_clk), - CLKDEV_CON_DEV_ID("usart", "f0020000.serial", &usart1_clk), - CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart2_clk), - CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart3_clk), - CLKDEV_CON_DEV_ID(NULL, "f0014000.i2c", &twi0_clk), - CLKDEV_CON_DEV_ID(NULL, "f0018000.i2c", &twi1_clk), - CLKDEV_CON_DEV_ID(NULL, "f801c000.i2c", &twi2_clk), - CLKDEV_CON_DEV_ID("mci_clk", "f0000000.mmc", &mmc0_clk), - CLKDEV_CON_DEV_ID("mci_clk", "f8000000.mmc", &mmc1_clk), - CLKDEV_CON_DEV_ID("mci_clk", "f8004000.mmc", &mmc2_clk), - CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi0_clk), - CLKDEV_CON_DEV_ID("spi_clk", "f8008000.spi", &spi1_clk), - CLKDEV_CON_DEV_ID("t0_clk", "f0010000.timer", &tcb0_clk), - CLKDEV_CON_DEV_ID("t0_clk", "f8014000.timer", &tcb1_clk), - CLKDEV_CON_DEV_ID("tsc_clk", "f8018000.tsadcc", &adc_clk), - CLKDEV_CON_DEV_ID("dma_clk", "ffffe600.dma-controller", &dma0_clk), - CLKDEV_CON_DEV_ID("dma_clk", "ffffe800.dma-controller", &dma1_clk), - CLKDEV_CON_DEV_ID("hclk", "600000.ohci", &uhphs_clk), - CLKDEV_CON_DEV_ID("ohci_clk", "600000.ohci", &uhphs_clk), - CLKDEV_CON_DEV_ID("ehci_clk", "700000.ehci", &uhphs_clk), - CLKDEV_CON_DEV_ID("pclk", "500000.gadget", &udphs_clk), - CLKDEV_CON_DEV_ID("hclk", "500000.gadget", &utmi_clk), - CLKDEV_CON_DEV_ID("hclk", "f0028000.ethernet", &macb0_clk), - CLKDEV_CON_DEV_ID("pclk", "f0028000.ethernet", &macb0_clk), - CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb1_clk), - CLKDEV_CON_DEV_ID("pclk", "f802c000.ethernet", &macb1_clk), - CLKDEV_CON_DEV_ID("pclk", "f0008000.ssc", &ssc0_clk), - CLKDEV_CON_DEV_ID("pclk", "f000c000.ssc", &ssc1_clk), - CLKDEV_CON_DEV_ID("can_clk", "f000c000.can", &can0_clk), - CLKDEV_CON_DEV_ID("can_clk", "f8010000.can", &can1_clk), - CLKDEV_CON_DEV_ID("sha_clk", "f8034000.sha", &sha_clk), - CLKDEV_CON_DEV_ID("aes_clk", "f8038000.aes", &aes_clk), - CLKDEV_CON_DEV_ID("tdes_clk", "f803c000.tdes", &tdes_clk), -}; - -static void __init sama5d3_register_clocks(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) - clk_register(periph_clocks[i]); - - clkdev_add_table(periph_clocks_lookups, - ARRAY_SIZE(periph_clocks_lookups)); - - clk_register(&pck0); - clk_register(&pck1); - clk_register(&pck2); -} - -/* -------------------------------------------------------------------- * AT91SAM9x5 processor initialization * -------------------------------------------------------------------- */ @@ -378,6 +37,5 @@ static void __init sama5d3_initialize(void) AT91_SOC_START(sama5d3) .map_io = sama5d3_map_io, - .register_clocks = sama5d3_register_clocks, .init = sama5d3_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 094b3459c288..7d3f7cc61081 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -11,6 +11,7 @@ #include <linux/pm.h> #include <linux/of_address.h> #include <linux/pinctrl/machine.h> +#include <linux/clk/at91_pmc.h> #include <asm/system_misc.h> #include <asm/mach/map.h> @@ -18,7 +19,6 @@ #include <mach/hardware.h> #include <mach/cpu.h> #include <mach/at91_dbgu.h> -#include <mach/at91_pmc.h> #include "at91_shdwc.h" #include "soc.h" @@ -491,7 +491,8 @@ void __init at91rm9200_dt_initialize(void) at91_dt_clock_init(); /* Register the processor-specific clocks */ - at91_boot_soc.register_clocks(); + if (at91_boot_soc.register_clocks) + at91_boot_soc.register_clocks(); at91_boot_soc.init(); } @@ -506,7 +507,8 @@ void __init at91_dt_initialize(void) at91_dt_clock_init(); /* Register the processor-specific clocks */ - at91_boot_soc.register_clocks(); + if (at91_boot_soc.register_clocks) + at91_boot_soc.register_clocks(); if (at91_boot_soc.init) at91_boot_soc.init(); diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index c122bcff9f7c..0d1a89298ece 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -162,7 +162,7 @@ void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data) /***************************************************************************** * SoC RTC ****************************************************************************/ -void __init dove_rtc_init(void) +static void __init dove_rtc_init(void) { orion_rtc_init(DOVE_RTC_PHYS_BASE, IRQ_DOVE_RTC); } @@ -257,18 +257,9 @@ void __init dove_timer_init(void) } /***************************************************************************** - * Cryptographic Engines and Security Accelerator (CESA) - ****************************************************************************/ -void __init dove_crypto_init(void) -{ - orion_crypto_init(DOVE_CRYPT_PHYS_BASE, DOVE_CESA_PHYS_BASE, - DOVE_CESA_SIZE, IRQ_DOVE_CRYPTO); -} - -/***************************************************************************** * XOR 0 ****************************************************************************/ -void __init dove_xor0_init(void) +static void __init dove_xor0_init(void) { orion_xor0_init(DOVE_XOR0_PHYS_BASE, DOVE_XOR0_HIGH_PHYS_BASE, IRQ_DOVE_XOR_00, IRQ_DOVE_XOR_01); @@ -277,7 +268,7 @@ void __init dove_xor0_init(void) /***************************************************************************** * XOR 1 ****************************************************************************/ -void __init dove_xor1_init(void) +static void __init dove_xor1_init(void) { orion_xor1_init(DOVE_XOR1_PHYS_BASE, DOVE_XOR1_HIGH_PHYS_BASE, IRQ_DOVE_XOR_10, IRQ_DOVE_XOR_11); diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 9caa4fe95913..78188159484d 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -10,55 +10,21 @@ * warranty of any kind, whether express or implied. */ +#include <linux/clk.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_net.h> #include <linux/of_platform.h> -#include <linux/clk-provider.h> #include <linux/dma-mapping.h> #include <linux/irqchip.h> #include <linux/kexec.h> #include <asm/mach/arch.h> -#include <asm/mach/map.h> #include <mach/bridge-regs.h> -#include <linux/platform_data/usb-ehci-orion.h> -#include <plat/irq.h> #include <plat/common.h> #include "common.h" -/* - * There are still devices that doesn't know about DT yet. Get clock - * gates here and add a clock lookup alias, so that old platform - * devices still work. -*/ - -static void __init kirkwood_legacy_clk_init(void) -{ - - struct device_node *np = of_find_compatible_node( - NULL, NULL, "marvell,kirkwood-gating-clock"); - struct of_phandle_args clkspec; - struct clk *clk; - - clkspec.np = np; - clkspec.args_count = 1; - - /* - * The ethernet interfaces forget the MAC address assigned by - * u-boot if the clocks are turned off. Until proper DT support - * is available we always enable them for now. - */ - clkspec.args[0] = CGC_BIT_GE0; - clk = of_clk_get_from_provider(&clkspec); - clk_prepare_enable(clk); - - clkspec.args[0] = CGC_BIT_GE1; - clk = of_clk_get_from_provider(&clkspec); - clk_prepare_enable(clk); -} - #define MV643XX_ETH_MAC_ADDR_LOW 0x0414 #define MV643XX_ETH_MAC_ADDR_HIGH 0x0418 @@ -140,7 +106,7 @@ eth_fixup_skip: static void __init kirkwood_dt_init(void) { - pr_info("Kirkwood: %s, TCLK=%d.\n", kirkwood_id(), kirkwood_tclk); + pr_info("Kirkwood: %s.\n", kirkwood_id()); /* * Disable propagation of mbus errors to the CPU local bus, @@ -156,8 +122,6 @@ static void __init kirkwood_dt_init(void) kirkwood_cpufreq_init(); kirkwood_cpuidle_init(); - /* Setup clocks for legacy devices */ - kirkwood_legacy_clk_init(); kirkwood_pm_init(); kirkwood_dt_eth_fixup(); diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 58adf2fd9cfc..4e9d58148ca7 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -27,6 +27,7 @@ #include <asm/smp_plat.h> #include <asm/cacheflush.h> #include "armada-370-xp.h" +#include "coherency.h" unsigned long coherency_phys_base; static void __iomem *coherency_base; diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h index df33ad8a6c08..760226c41353 100644 --- a/arch/arm/mach-mvebu/coherency.h +++ b/arch/arm/mach-mvebu/coherency.h @@ -14,7 +14,9 @@ #ifndef __MACH_370_XP_COHERENCY_H #define __MACH_370_XP_COHERENCY_H -int set_cpu_coherent(int cpu_id, int smp_group_id); +extern unsigned long coherency_phys_base; + +int set_cpu_coherent(unsigned int cpu_id, int smp_group_id); int coherency_init(void); #endif /* __MACH_370_XP_COHERENCY_H */ diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h index e366010e1d91..0e6016fadcc5 100644 --- a/arch/arm/mach-mvebu/common.h +++ b/arch/arm/mach-mvebu/common.h @@ -26,7 +26,6 @@ void armada_370_xp_handle_irq(struct pt_regs *regs); void armada_xp_cpu_die(unsigned int cpu); int armada_370_xp_coherency_init(void); -int armada_370_xp_pmsu_init(void); void armada_xp_secondary_startup(void); extern struct smp_operations armada_xp_smp_ops; #endif diff --git a/arch/arm/mach-mvebu/hotplug.c b/arch/arm/mach-mvebu/hotplug.c index b228b6a80c85..d95e91047168 100644 --- a/arch/arm/mach-mvebu/hotplug.c +++ b/arch/arm/mach-mvebu/hotplug.c @@ -15,6 +15,7 @@ #include <linux/errno.h> #include <linux/smp.h> #include <asm/proc-fns.h> +#include "common.h" /* * platform-specific code to shutdown a CPU diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index ff69c2df298b..a6da03f5b24e 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -46,7 +46,7 @@ static struct clk *__init get_cpu_clk(int cpu) return cpu_clk; } -void __init set_secondary_cpus_clock(void) +static void __init set_secondary_cpus_clock(void) { int thiscpu, cpu; unsigned long rate; @@ -94,7 +94,7 @@ static void __init armada_xp_smp_init_cpus(void) set_smp_cross_call(armada_mpic_send_doorbell); } -void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) +static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) { struct device_node *node; struct resource res; diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 27fc4f049474..d71ef53107c4 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -22,6 +22,7 @@ #include <linux/io.h> #include <linux/smp.h> #include <asm/smp_plat.h> +#include "pmsu.h" static void __iomem *pmsu_mp_base; static void __iomem *pmsu_reset_base; @@ -58,7 +59,7 @@ int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr) } #endif -int __init armada_370_xp_pmsu_init(void) +static int __init armada_370_xp_pmsu_init(void) { struct device_node *np; diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c index 5175083cdb34..a7fb89a5b5d9 100644 --- a/arch/arm/mach-mvebu/system-controller.c +++ b/arch/arm/mach-mvebu/system-controller.c @@ -27,6 +27,7 @@ #include <linux/of_address.h> #include <linux/io.h> #include <linux/reboot.h> +#include "common.h" static void __iomem *system_controller_base; @@ -39,14 +40,14 @@ struct mvebu_system_controller { }; static struct mvebu_system_controller *mvebu_sc; -const struct mvebu_system_controller armada_370_xp_system_controller = { +static const struct mvebu_system_controller armada_370_xp_system_controller = { .rstoutn_mask_offset = 0x60, .system_soft_reset_offset = 0x64, .rstoutn_mask_reset_out_en = 0x1, .system_soft_reset = 0x1, }; -const struct mvebu_system_controller orion_system_controller = { +static const struct mvebu_system_controller orion_system_controller = { .rstoutn_mask_offset = 0x108, .system_soft_reset_offset = 0x10c, .rstoutn_mask_reset_out_en = 0x4, diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c index 365bfd3d9c68..dadccc91488c 100644 --- a/arch/arm/mach-omap2/dss-common.c +++ b/arch/arm/mach-omap2/dss-common.c @@ -223,7 +223,7 @@ void __init omap_4430sdp_display_init_of(void) static struct connector_dvi_platform_data omap3_igep2_dvi_connector_pdata = { .name = "dvi", .source = "tfp410.0", - .i2c_bus_num = 3, + .i2c_bus_num = 2, }; static struct platform_device omap3_igep2_dvi_connector_device = { diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 10c71450cf63..39f020c982e8 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -139,6 +139,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { static struct pdata_init pdata_quirks[] __initdata = { #ifdef CONFIG_ARCH_OMAP3 + { "nokia,omap3-n900", hsmmc2_internal_input_clk, }, { "nokia,omap3-n9", hsmmc2_internal_input_clk, }, { "nokia,omap3-n950", hsmmc2_internal_input_clk, }, { "isee,omap3-igep0020", omap3_igep0020_legacy_init, }, diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index e233dfcbc186..93a2a6e4260f 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -128,7 +128,8 @@ skip_voltdm: for (i = 0; i < pwrdm->banks; i++) pwrdm->ret_mem_off_counter[i] = 0; - arch_pwrdm->pwrdm_wait_transition(pwrdm); + if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition) + arch_pwrdm->pwrdm_wait_transition(pwrdm); pwrdm->state = pwrdm_read_pwrst(pwrdm); pwrdm->state_counter[pwrdm->state] = 1; diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c index b91002ca92f3..c134a826070a 100644 --- a/arch/arm/mach-orion5x/board-dt.c +++ b/arch/arm/mach-orion5x/board-dt.c @@ -21,7 +21,7 @@ #include <plat/irq.h> #include "common.h" -struct of_dev_auxdata orion5x_auxdata_lookup[] __initdata = { +static struct of_dev_auxdata orion5x_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL), OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0", NULL), diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 91a5852b44f3..3f1de1111e0f 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -24,7 +24,6 @@ #include <asm/page.h> #include <asm/setup.h> #include <asm/system_misc.h> -#include <asm/timex.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -135,7 +134,7 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data) /***************************************************************************** * SPI ****************************************************************************/ -void __init orion5x_spi_init() +void __init orion5x_spi_init(void) { orion_spi_init(SPI_PHYS_BASE); } @@ -185,7 +184,7 @@ static void __init orion5x_crypto_init(void) /***************************************************************************** * Watchdog ****************************************************************************/ -void __init orion5x_wdt_init(void) +static void __init orion5x_wdt_init(void) { orion_wdt_init(); } @@ -246,7 +245,7 @@ void orion5x_setup_wins(void) int orion5x_tclk; -int __init orion5x_find_tclk(void) +static int __init orion5x_find_tclk(void) { u32 dev, rev; diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c index 4b2aefd1d961..dc01c4ffc9a8 100644 --- a/arch/arm/mach-orion5x/db88f5281-setup.c +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -202,7 +202,7 @@ __initcall(db88f5281_7seg_init); * PCI ****************************************************************************/ -void __init db88f5281_pci_preinit(void) +static void __init db88f5281_pci_preinit(void) { int pin; diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c index 30a192b9c517..9654b0cc5892 100644 --- a/arch/arm/mach-orion5x/irq.c +++ b/arch/arm/mach-orion5x/irq.c @@ -16,6 +16,7 @@ #include <mach/bridge-regs.h> #include <plat/orion-gpio.h> #include <plat/irq.h> +#include "common.h" static int __initdata gpio0_irqs[4] = { IRQ_ORION5X_GPIO_0_7, diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c index 7fab67053030..87a12d6930ff 100644 --- a/arch/arm/mach-orion5x/pci.c +++ b/arch/arm/mach-orion5x/pci.c @@ -240,11 +240,11 @@ static int __init pcie_setup(struct pci_sys_data *sys) #define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc08) : \ ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \ ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \ - ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0) + ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : NULL) #define PCI_BAR_REMAP_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc48) : \ ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \ ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \ - ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0) + ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : NULL) #define PCI_BAR_ENABLE ORION5X_PCI_REG(0xc3c) #define PCI_ADDR_DECODE_CTRL ORION5X_PCI_REG(0xd3c) diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c index b1cf68493ffc..b576ef5f18a1 100644 --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -108,7 +108,7 @@ static struct platform_device rd88f5182_gpio_leds = { * PCI ****************************************************************************/ -void __init rd88f5182_pci_preinit(void) +static void __init rd88f5182_pci_preinit(void) { int pin; diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c index 7e9064844698..6208d125c1b9 100644 --- a/arch/arm/mach-orion5x/terastation_pro2-setup.c +++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c @@ -77,7 +77,7 @@ static struct platform_device tsp2_nor_flash = { #define TSP2_PCI_SLOT0_OFFS 7 #define TSP2_PCI_SLOT0_IRQ_PIN 11 -void __init tsp2_pci_preinit(void) +static void __init tsp2_pci_preinit(void) { int pin; diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c index e90c0618fdad..9136797addb2 100644 --- a/arch/arm/mach-orion5x/ts209-setup.c +++ b/arch/arm/mach-orion5x/ts209-setup.c @@ -106,7 +106,7 @@ static struct platform_device qnap_ts209_nor_flash = { #define QNAP_TS209_PCI_SLOT0_IRQ_PIN 6 #define QNAP_TS209_PCI_SLOT1_IRQ_PIN 7 -void __init qnap_ts209_pci_preinit(void) +static void __init qnap_ts209_pci_preinit(void) { int pin; diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index e960855d32ac..db16dae441e2 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -57,7 +57,7 @@ static struct map_desc ts78xx_io_desc[] __initdata = { }, }; -void __init ts78xx_map_io(void) +static void __init ts78xx_map_io(void) { orion5x_map_io(); iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc)); diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c index 0fa068e30a30..fe071a9130b7 100644 --- a/arch/arm/mach-shmobile/board-ape6evm.c +++ b/arch/arm/mach-shmobile/board-ape6evm.c @@ -168,7 +168,7 @@ static const struct sh_mmcif_plat_data mmcif0_pdata __initconst = { }; static const struct resource mmcif0_resources[] __initconst = { - DEFINE_RES_MEM_NAMED(0xee200000, 0x100, "MMCIF0"), + DEFINE_RES_MEM(0xee200000, 0x100), DEFINE_RES_IRQ(gic_spi(169)), }; @@ -179,7 +179,7 @@ static const struct sh_mobile_sdhi_info sdhi0_pdata __initconst = { }; static const struct resource sdhi0_resources[] __initconst = { - DEFINE_RES_MEM_NAMED(0xee100000, 0x100, "SDHI0"), + DEFINE_RES_MEM(0xee100000, 0x100), DEFINE_RES_IRQ(gic_spi(165)), }; @@ -191,7 +191,7 @@ static const struct sh_mobile_sdhi_info sdhi1_pdata __initconst = { }; static const struct resource sdhi1_resources[] __initconst = { - DEFINE_RES_MEM_NAMED(0xee120000, 0x100, "SDHI1"), + DEFINE_RES_MEM(0xee120000, 0x100), DEFINE_RES_IRQ(gic_spi(166)), }; diff --git a/arch/arm/mach-shmobile/board-bockw-reference.c b/arch/arm/mach-shmobile/board-bockw-reference.c index ae88fdad4b3a..1687df9b267f 100644 --- a/arch/arm/mach-shmobile/board-bockw-reference.c +++ b/arch/arm/mach-shmobile/board-bockw-reference.c @@ -19,7 +19,6 @@ */ #include <linux/of_platform.h> -#include <linux/pinctrl/machine.h> #include <mach/common.h> #include <mach/r8a7778.h> #include <asm/mach/arch.h> diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c index 1a1a4a888632..7df9ea0839db 100644 --- a/arch/arm/mach-shmobile/board-lager-reference.c +++ b/arch/arm/mach-shmobile/board-lager-reference.c @@ -20,16 +20,15 @@ #include <linux/init.h> #include <linux/of_platform.h> +#include <mach/rcar-gen2.h> #include <mach/r8a7790.h> #include <asm/mach/arch.h> static void __init lager_add_standard_devices(void) { - /* clocks are setup late during boot in the case of DT */ r8a7790_clock_init(); - r8a7790_add_dt_devices(); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } static const char *lager_boards_compat_dt[] __initdata = { diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c index a8d3ce646fb9..78a31b667988 100644 --- a/arch/arm/mach-shmobile/board-lager.c +++ b/arch/arm/mach-shmobile/board-lager.c @@ -148,7 +148,7 @@ static const struct sh_mmcif_plat_data mmcif1_pdata __initconst = { }; static const struct resource mmcif1_resources[] __initconst = { - DEFINE_RES_MEM_NAMED(0xee220000, 0x80, "MMCIF1"), + DEFINE_RES_MEM(0xee220000, 0x80), DEFINE_RES_IRQ(gic_spi(170)), }; diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index da1352f5f71b..4f9e3ec42ddc 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c @@ -29,6 +29,7 @@ #include <linux/leds.h> #include <linux/dma-mapping.h> #include <linux/pinctrl/machine.h> +#include <linux/platform_data/camera-rcar.h> #include <linux/platform_data/gpio-rcar.h> #include <linux/platform_data/rcar-du.h> #include <linux/platform_data/usb-rcar-phy.h> @@ -259,10 +260,30 @@ static struct platform_device leds_device = { }, }; +/* VIN */ static struct rcar_vin_platform_data vin_platform_data __initdata = { .flags = RCAR_VIN_BT656, }; +#define MARZEN_VIN(idx) \ +static struct resource vin##idx##_resources[] __initdata = { \ + DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \ + DEFINE_RES_IRQ(gic_iid(0x5f + (idx))), \ +}; \ + \ +static struct platform_device_info vin##idx##_info __initdata = { \ + .parent = &platform_bus, \ + .name = "r8a7779-vin", \ + .id = idx, \ + .res = vin##idx##_resources, \ + .num_res = ARRAY_SIZE(vin##idx##_resources), \ + .dma_mask = DMA_BIT_MASK(32), \ + .data = &vin_platform_data, \ + .size_data = sizeof(vin_platform_data), \ +} +MARZEN_VIN(1); +MARZEN_VIN(3); + #define MARZEN_CAMERA(idx) \ static struct i2c_board_info camera##idx##_info = { \ I2C_BOARD_INFO("adv7180", 0x20 + (idx)), \ @@ -367,8 +388,8 @@ static void __init marzen_init(void) r8a7779_init_irq_extpin(1); /* IRQ1 as individual interrupt */ r8a7779_add_standard_devices(); - r8a7779_add_vin_device(1, &vin_platform_data); - r8a7779_add_vin_device(3, &vin_platform_data); + platform_device_register_full(&vin1_info); + platform_device_register_full(&vin3_info); platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices)); marzen_add_du_device(); } diff --git a/arch/arm/mach-shmobile/clock-r7s72100.c b/arch/arm/mach-shmobile/clock-r7s72100.c index 4aba20ca127e..0814a508fd61 100644 --- a/arch/arm/mach-shmobile/clock-r7s72100.c +++ b/arch/arm/mach-shmobile/clock-r7s72100.c @@ -170,6 +170,9 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), /* MSTP clocks */ + CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP33]), + + /* ICK */ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]), CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]), CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]), diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c index a64f965c7da1..fa1b4773677a 100644 --- a/arch/arm/mach-shmobile/clock-r8a7790.c +++ b/arch/arm/mach-shmobile/clock-r8a7790.c @@ -77,7 +77,7 @@ static struct sh_clk_ops followparent_clk_ops = { }; static struct clk main_clk = { - /* .parent will be set r8a73a4_clock_init */ + /* .parent will be set r8a7790_clock_init */ .ops = &followparent_clk_ops, }; diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 5390c6bbbc02..28489978b09c 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -504,10 +504,6 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]), CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]), - CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), - CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), - CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), - CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */ @@ -574,6 +570,11 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ CLKDEV_DEV_ID("sh_cmt.2", &mstp_clks[MSTP400]), /* CMT2 */ + /* ICK */ + CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), + CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), CLKDEV_ICK_ID("hdmi", "sh_mobile_lcdc_fb.1", &div6_reparent_clks[DIV6_HDMI]), CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index c92c023f0d27..2aeec468cf7c 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -625,12 +625,6 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("sdhi0_clk", &div6_clks[DIV6_SDHI0]), CLKDEV_CON_ID("sdhi1_clk", &div6_clks[DIV6_SDHI1]), CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]), - CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), - CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), - CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), - CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), - CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk), - CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk), /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */ @@ -680,6 +674,14 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ + + /* ICK */ + CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), + CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), + CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk), + CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk), }; void __init sh73a0_clock_init(void) diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h index 17af34ed89c8..5014145f272e 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7779.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h @@ -3,8 +3,6 @@ #include <linux/sh_clk.h> #include <linux/pm_domain.h> -#include <linux/sh_eth.h> -#include <linux/platform_data/camera-rcar.h> /* HPB-DMA slave IDs */ enum { @@ -40,9 +38,6 @@ extern void r8a7779_earlytimer_init(void); extern void r8a7779_add_early_devices(void); extern void r8a7779_add_standard_devices(void); extern void r8a7779_add_standard_devices_dt(void); -extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata); -extern void r8a7779_add_vin_device(int idx, - struct rcar_vin_platform_data *pdata); extern void r8a7779_init_late(void); extern void r8a7779_clock_init(void); extern void r8a7779_pinmux_init(void); diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 13049e9d691c..8f9453152fb9 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -598,45 +598,6 @@ static struct platform_device ohci1_device = { .resource = ohci1_resources, }; -/* Ether */ -static struct resource ether_resources[] __initdata = { - { - .start = 0xfde00000, - .end = 0xfde003ff, - .flags = IORESOURCE_MEM, - }, { - .start = gic_iid(0xb4), - .flags = IORESOURCE_IRQ, - }, -}; - -#define R8A7779_VIN(idx) \ -static struct resource vin##idx##_resources[] __initdata = { \ - DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \ - DEFINE_RES_IRQ(gic_iid(0x5f + (idx))), \ -}; \ - \ -static struct platform_device_info vin##idx##_info __initdata = { \ - .parent = &platform_bus, \ - .name = "r8a7779-vin", \ - .id = idx, \ - .res = vin##idx##_resources, \ - .num_res = ARRAY_SIZE(vin##idx##_resources), \ - .dma_mask = DMA_BIT_MASK(32), \ -} - -R8A7779_VIN(0); -R8A7779_VIN(1); -R8A7779_VIN(2); -R8A7779_VIN(3); - -static struct platform_device_info *vin_info_table[] __initdata = { - &vin0_info, - &vin1_info, - &vin2_info, - &vin3_info, -}; - /* HPB-DMA */ /* Asynchronous mode register bits */ @@ -825,24 +786,6 @@ void __init r8a7779_add_standard_devices(void) r8a7779_register_hpb_dmae(); } -void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata) -{ - platform_device_register_resndata(&platform_bus, "r8a777x-ether", -1, - ether_resources, - ARRAY_SIZE(ether_resources), - pdata, sizeof(*pdata)); -} - -void __init r8a7779_add_vin_device(int id, struct rcar_vin_platform_data *pdata) -{ - BUG_ON(id < 0 || id > 3); - - vin_info_table[id]->data = pdata; - vin_info_table[id]->size_data = sizeof(*pdata); - - platform_device_register_full(vin_info_table[id]); -} - /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ void __init __weak r8a7779_register_twd(void) { } diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c index c47bcebbcb00..3543c3bacb75 100644 --- a/arch/arm/mach-shmobile/setup-r8a7790.c +++ b/arch/arm/mach-shmobile/setup-r8a7790.c @@ -34,6 +34,10 @@ static const struct resource pfc_resources[] __initconst = { DEFINE_RES_MEM(0xe6060000, 0x250), }; +#define r8a7790_register_pfc() \ + platform_device_register_simple("pfc-r8a7790", -1, pfc_resources, \ + ARRAY_SIZE(pfc_resources)) + #define R8A7790_GPIO(idx) \ static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \ DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \ @@ -65,8 +69,7 @@ R8A7790_GPIO(5); void __init r8a7790_pinmux_init(void) { - platform_device_register_simple("pfc-r8a7790", -1, pfc_resources, - ARRAY_SIZE(pfc_resources)); + r8a7790_register_pfc(); r8a7790_register_gpio(0); r8a7790_register_gpio(1); r8a7790_register_gpio(2); diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index 22de17417fd7..65151c48cbd4 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -273,7 +273,7 @@ static struct sh_timer_config tmu00_platform_data = { }; static struct resource tmu00_resources[] = { - [0] = DEFINE_RES_MEM_NAMED(0xfff60008, 0xc, "TMU00"), + [0] = DEFINE_RES_MEM(0xfff60008, 0xc), [1] = { .start = intcs_evt2irq(0x0e80), /* TMU0_TUNI00 */ .flags = IORESOURCE_IRQ, @@ -298,7 +298,7 @@ static struct sh_timer_config tmu01_platform_data = { }; static struct resource tmu01_resources[] = { - [0] = DEFINE_RES_MEM_NAMED(0xfff60014, 0xc, "TMU00"), + [0] = DEFINE_RES_MEM(0xfff60014, 0xc), [1] = { .start = intcs_evt2irq(0x0ea0), /* TMU0_TUNI01 */ .flags = IORESOURCE_IRQ, @@ -316,7 +316,7 @@ static struct platform_device tmu01_device = { }; static struct resource i2c0_resources[] = { - [0] = DEFINE_RES_MEM_NAMED(0xe6820000, 0x426, "IIC0"), + [0] = DEFINE_RES_MEM(0xe6820000, 0x426), [1] = { .start = gic_spi(167), .end = gic_spi(170), @@ -325,7 +325,7 @@ static struct resource i2c0_resources[] = { }; static struct resource i2c1_resources[] = { - [0] = DEFINE_RES_MEM_NAMED(0xe6822000, 0x426, "IIC1"), + [0] = DEFINE_RES_MEM(0xe6822000, 0x426), [1] = { .start = gic_spi(51), .end = gic_spi(54), @@ -334,7 +334,7 @@ static struct resource i2c1_resources[] = { }; static struct resource i2c2_resources[] = { - [0] = DEFINE_RES_MEM_NAMED(0xe6824000, 0x426, "IIC2"), + [0] = DEFINE_RES_MEM(0xe6824000, 0x426), [1] = { .start = gic_spi(171), .end = gic_spi(174), @@ -343,7 +343,7 @@ static struct resource i2c2_resources[] = { }; static struct resource i2c3_resources[] = { - [0] = DEFINE_RES_MEM_NAMED(0xe6826000, 0x426, "IIC3"), + [0] = DEFINE_RES_MEM(0xe6826000, 0x426), [1] = { .start = gic_spi(183), .end = gic_spi(186), @@ -352,7 +352,7 @@ static struct resource i2c3_resources[] = { }; static struct resource i2c4_resources[] = { - [0] = DEFINE_RES_MEM_NAMED(0xe6828000, 0x426, "IIC4"), + [0] = DEFINE_RES_MEM(0xe6828000, 0x426), [1] = { .start = gic_spi(187), .end = gic_spi(190), @@ -722,7 +722,7 @@ static struct platform_device pmu_device = { /* an IPMMU module for ICB */ static struct resource ipmmu_resources[] = { - DEFINE_RES_MEM_NAMED(0xfe951000, 0x100, "IPMMU"), + DEFINE_RES_MEM(0xfe951000, 0x100), }; static const char * const ipmmu_dev_names[] = { diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 037100a1563a..aee77f06f887 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -10,6 +10,7 @@ config ARCH_SOCFPGA select GENERIC_CLOCKEVENTS select GPIO_PL061 if GPIOLIB select HAVE_ARM_SCU + select HAVE_ARM_TWD if SMP select HAVE_SMP select MFD_SYSCON select SPARSE_IRQ diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 840452b89fc2..d8f5ce430fa7 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -151,6 +151,10 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { /* Requires call-back bindings. */ OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata), /* Requires DMA bindings. */ + OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0", &mop500_sdi0_data), + OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1", &mop500_sdi1_data), + OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2", &mop500_sdi2_data), + OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4", &mop500_sdi4_data), OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000, "ux500-msp-i2s.0", &msp0_platform_data), OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000, diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index fb92abb91628..2861b155485a 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -336,8 +336,11 @@ static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer) if (timer->posted) return; - if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) + if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) { + timer->posted = OMAP_TIMER_NONPOSTED; + __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0, 0); return; + } __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, OMAP_TIMER_CTRL_POSTED, 0); diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c index c66d163d7a2a..830ff07f3385 100644 --- a/arch/arm/plat-orion/common.c +++ b/arch/arm/plat-orion/common.c @@ -22,6 +22,7 @@ #include <linux/platform_data/dma-mv_xor.h> #include <linux/platform_data/usb-ehci-orion.h> #include <mach/bridge-regs.h> +#include <plat/common.h> /* Create a clkdev entry for a given device/clk */ void __init orion_clkdev_add(const char *con_id, const char *dev_id, @@ -256,7 +257,7 @@ static __init void ge_complete( /***************************************************************************** * GE00 ****************************************************************************/ -struct mv643xx_eth_shared_platform_data orion_ge00_shared_data; +static struct mv643xx_eth_shared_platform_data orion_ge00_shared_data; static struct resource orion_ge00_shared_resources[] = { { @@ -322,7 +323,7 @@ void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data, /***************************************************************************** * GE01 ****************************************************************************/ -struct mv643xx_eth_shared_platform_data orion_ge01_shared_data; +static struct mv643xx_eth_shared_platform_data orion_ge01_shared_data; static struct resource orion_ge01_shared_resources[] = { { @@ -373,7 +374,7 @@ void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data, /***************************************************************************** * GE10 ****************************************************************************/ -struct mv643xx_eth_shared_platform_data orion_ge10_shared_data; +static struct mv643xx_eth_shared_platform_data orion_ge10_shared_data; static struct resource orion_ge10_shared_resources[] = { { @@ -422,7 +423,7 @@ void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data, /***************************************************************************** * GE11 ****************************************************************************/ -struct mv643xx_eth_shared_platform_data orion_ge11_shared_data; +static struct mv643xx_eth_shared_platform_data orion_ge11_shared_data; static struct resource orion_ge11_shared_resources[] = { { diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 9d2b2ac74938..15921a1839d7 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -17,6 +17,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/sched_clock.h> +#include <plat/time.h> /* * MBus bridge block registers. @@ -174,7 +175,7 @@ static irqreturn_t orion_timer_interrupt(int irq, void *dev_id) static struct irqaction orion_timer_irq = { .name = "orion_tick", - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .handler = orion_timer_interrupt }; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7a10bc9a23e7..ace7309c4369 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ +obj-$(CONFIG_COMMON_CLK_AT91) += at91/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile new file mode 100644 index 000000000000..0e92b716f934 --- /dev/null +++ b/drivers/clk/at91/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for at91 specific clk +# + +obj-y += pmc.o +obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o +obj-y += clk-system.o clk-peripheral.o + +obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o +obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o +obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o +obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c new file mode 100644 index 000000000000..8e9e8cc0412d --- /dev/null +++ b/drivers/clk/at91/clk-main.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/sched.h> +#include <linux/wait.h> + +#include "pmc.h" + +#define SLOW_CLOCK_FREQ 32768 +#define MAINF_DIV 16 +#define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \ + SLOW_CLOCK_FREQ) +#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ) +#define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT + +struct clk_main { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned long rate; + unsigned int irq; + wait_queue_head_t wait; +}; + +#define to_clk_main(hw) container_of(hw, struct clk_main, hw) + +static irqreturn_t clk_main_irq_handler(int irq, void *dev_id) +{ + struct clk_main *clkmain = (struct clk_main *)dev_id; + + wake_up(&clkmain->wait); + disable_irq_nosync(clkmain->irq); + + return IRQ_HANDLED; +} + +static int clk_main_prepare(struct clk_hw *hw) +{ + struct clk_main *clkmain = to_clk_main(hw); + struct at91_pmc *pmc = clkmain->pmc; + unsigned long halt_time, timeout; + u32 tmp; + + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) { + enable_irq(clkmain->irq); + wait_event(clkmain->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); + } + + if (clkmain->rate) + return 0; + + timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); + do { + halt_time = jiffies; + tmp = pmc_read(pmc, AT91_CKGR_MCFR); + if (tmp & AT91_PMC_MAINRDY) + return 0; + usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); + } while (time_before(halt_time, timeout)); + + return 0; +} + +static int clk_main_is_prepared(struct clk_hw *hw) +{ + struct clk_main *clkmain = to_clk_main(hw); + + return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); +} + +static unsigned long clk_main_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + struct clk_main *clkmain = to_clk_main(hw); + struct at91_pmc *pmc = clkmain->pmc; + + if (clkmain->rate) + return clkmain->rate; + + tmp = pmc_read(pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINF; + clkmain->rate = (tmp * parent_rate) / MAINF_DIV; + + return clkmain->rate; +} + +static const struct clk_ops main_ops = { + .prepare = clk_main_prepare, + .is_prepared = clk_main_is_prepared, + .recalc_rate = clk_main_recalc_rate, +}; + +static struct clk * __init +at91_clk_register_main(struct at91_pmc *pmc, + unsigned int irq, + const char *name, + const char *parent_name, + unsigned long rate) +{ + int ret; + struct clk_main *clkmain; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !irq || !name) + return ERR_PTR(-EINVAL); + + if (!rate && !parent_name) + return ERR_PTR(-EINVAL); + + clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); + if (!clkmain) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &main_ops; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.flags = parent_name ? 0 : CLK_IS_ROOT; + + clkmain->hw.init = &init; + clkmain->rate = rate; + clkmain->pmc = pmc; + clkmain->irq = irq; + init_waitqueue_head(&clkmain->wait); + irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN); + ret = request_irq(clkmain->irq, clk_main_irq_handler, + IRQF_TRIGGER_HIGH, "clk-main", clkmain); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &clkmain->hw); + if (IS_ERR(clk)) { + free_irq(clkmain->irq, clkmain); + kfree(clkmain); + } + + return clk; +} + + + +static void __init +of_at91_clk_main_setup(struct device_node *np, struct at91_pmc *pmc) +{ + struct clk *clk; + unsigned int irq; + const char *parent_name; + const char *name = np->name; + u32 rate = 0; + + parent_name = of_clk_get_parent_name(np, 0); + of_property_read_string(np, "clock-output-names", &name); + of_property_read_u32(np, "clock-frequency", &rate); + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_main(pmc, irq, name, parent_name, rate); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +void __init of_at91rm9200_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_main_setup(np, pmc); +} diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c new file mode 100644 index 000000000000..bd313f7816a8 --- /dev/null +++ b/drivers/clk/at91/clk-master.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/io.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include "pmc.h" + +#define MASTER_SOURCE_MAX 4 + +#define MASTER_PRES_MASK 0x7 +#define MASTER_PRES_MAX MASTER_PRES_MASK +#define MASTER_DIV_SHIFT 8 +#define MASTER_DIV_MASK 0x3 + +struct clk_master_characteristics { + struct clk_range output; + u32 divisors[4]; + u8 have_div3_pres; +}; + +struct clk_master_layout { + u32 mask; + u8 pres_shift; +}; + +#define to_clk_master(hw) container_of(hw, struct clk_master, hw) + +struct clk_master { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + const struct clk_master_layout *layout; + const struct clk_master_characteristics *characteristics; +}; + +static irqreturn_t clk_master_irq_handler(int irq, void *dev_id) +{ + struct clk_master *master = (struct clk_master *)dev_id; + + wake_up(&master->wait); + disable_irq_nosync(master->irq); + + return IRQ_HANDLED; +} +static int clk_master_prepare(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master->pmc; + + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY)) { + enable_irq(master->irq); + wait_event(master->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); + } + + return 0; +} + +static int clk_master_is_prepared(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + + return !!(pmc_read(master->pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY); +} + +static unsigned long clk_master_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u8 pres; + u8 div; + unsigned long rate = parent_rate; + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master->pmc; + const struct clk_master_layout *layout = master->layout; + const struct clk_master_characteristics *characteristics = + master->characteristics; + u32 tmp; + + pmc_lock(pmc); + tmp = pmc_read(pmc, AT91_PMC_MCKR) & layout->mask; + pmc_unlock(pmc); + + pres = (tmp >> layout->pres_shift) & MASTER_PRES_MASK; + div = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; + + if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX) + rate /= 3; + else + rate >>= pres; + + rate /= characteristics->divisors[div]; + + if (rate < characteristics->output.min) + pr_warn("master clk is underclocked"); + else if (rate > characteristics->output.max) + pr_warn("master clk is overclocked"); + + return rate; +} + +static u8 clk_master_get_parent(struct clk_hw *hw) +{ + struct clk_master *master = to_clk_master(hw); + struct at91_pmc *pmc = master->pmc; + + return pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_CSS; +} + +static const struct clk_ops master_ops = { + .prepare = clk_master_prepare, + .is_prepared = clk_master_is_prepared, + .recalc_rate = clk_master_recalc_rate, + .get_parent = clk_master_get_parent, +}; + +static struct clk * __init +at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, + const char *name, int num_parents, + const char **parent_names, + const struct clk_master_layout *layout, + const struct clk_master_characteristics *characteristics) +{ + int ret; + struct clk_master *master; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !irq || !name || !num_parents || !parent_names) + return ERR_PTR(-EINVAL); + + master = kzalloc(sizeof(*master), GFP_KERNEL); + if (!master) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &master_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = 0; + + master->hw.init = &init; + master->layout = layout; + master->characteristics = characteristics; + master->pmc = pmc; + master->irq = irq; + init_waitqueue_head(&master->wait); + irq_set_status_flags(master->irq, IRQ_NOAUTOEN); + ret = request_irq(master->irq, clk_master_irq_handler, + IRQF_TRIGGER_HIGH, "clk-master", master); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &master->hw); + if (IS_ERR(clk)) + kfree(master); + + return clk; +} + + +static const struct clk_master_layout at91rm9200_master_layout = { + .mask = 0x31F, + .pres_shift = 2, +}; + +static const struct clk_master_layout at91sam9x5_master_layout = { + .mask = 0x373, + .pres_shift = 4, +}; + + +static struct clk_master_characteristics * __init +of_at91_clk_master_get_characteristics(struct device_node *np) +{ + struct clk_master_characteristics *characteristics; + + characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL); + if (!characteristics) + return NULL; + + if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output)) + goto out_free_characteristics; + + of_property_read_u32_array(np, "atmel,clk-divisors", + characteristics->divisors, 4); + + characteristics->have_div3_pres = + of_property_read_bool(np, "atmel,master-clk-have-div3-pres"); + + return characteristics; + +out_free_characteristics: + kfree(characteristics); + return NULL; +} + +static void __init +of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc, + const struct clk_master_layout *layout) +{ + struct clk *clk; + int num_parents; + int i; + unsigned int irq; + const char *parent_names[MASTER_SOURCE_MAX]; + const char *name = np->name; + struct clk_master_characteristics *characteristics; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX) + return; + + for (i = 0; i < num_parents; ++i) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + of_property_read_string(np, "clock-output-names", &name); + + characteristics = of_at91_clk_master_get_characteristics(np); + if (!characteristics) + return; + + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_master(pmc, irq, name, num_parents, + parent_names, layout, + characteristics); + if (IS_ERR(clk)) + goto out_free_characteristics; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; + +out_free_characteristics: + kfree(characteristics); +} + +void __init of_at91rm9200_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_master_setup(np, pmc, &at91rm9200_master_layout); +} + +void __init of_at91sam9x5_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_master_setup(np, pmc, &at91sam9x5_master_layout); +} diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c new file mode 100644 index 000000000000..597fed423d7d --- /dev/null +++ b/drivers/clk/at91/clk-peripheral.c @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> + +#include "pmc.h" + +#define PERIPHERAL_MAX 64 + +#define PERIPHERAL_AT91RM9200 0 +#define PERIPHERAL_AT91SAM9X5 1 + +#define PERIPHERAL_ID_MIN 2 +#define PERIPHERAL_ID_MAX 31 +#define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX)) + +#define PERIPHERAL_RSHIFT_MASK 0x3 +#define PERIPHERAL_RSHIFT(val) (((val) >> 16) & PERIPHERAL_RSHIFT_MASK) + +#define PERIPHERAL_MAX_SHIFT 4 + +struct clk_peripheral { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 id; +}; + +#define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw) + +struct clk_sam9x5_peripheral { + struct clk_hw hw; + struct at91_pmc *pmc; + struct clk_range range; + u32 id; + u32 div; + bool auto_div; +}; + +#define to_clk_sam9x5_peripheral(hw) \ + container_of(hw, struct clk_sam9x5_peripheral, hw) + +static int clk_peripheral_enable(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCER; + u32 id = periph->id; + + if (id < PERIPHERAL_ID_MIN) + return 0; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCER1; + pmc_write(pmc, offset, PERIPHERAL_MASK(id)); + return 0; +} + +static void clk_peripheral_disable(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCDR; + u32 id = periph->id; + + if (id < PERIPHERAL_ID_MIN) + return; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCDR1; + pmc_write(pmc, offset, PERIPHERAL_MASK(id)); +} + +static int clk_peripheral_is_enabled(struct clk_hw *hw) +{ + struct clk_peripheral *periph = to_clk_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + int offset = AT91_PMC_PCSR; + u32 id = periph->id; + + if (id < PERIPHERAL_ID_MIN) + return 1; + if (id > PERIPHERAL_ID_MAX) + offset = AT91_PMC_PCSR1; + return !!(pmc_read(pmc, offset) & PERIPHERAL_MASK(id)); +} + +static const struct clk_ops peripheral_ops = { + .enable = clk_peripheral_enable, + .disable = clk_peripheral_disable, + .is_enabled = clk_peripheral_is_enabled, +}; + +static struct clk * __init +at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, + const char *parent_name, u32 id) +{ + struct clk_peripheral *periph; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !name || !parent_name || id > PERIPHERAL_ID_MAX) + return ERR_PTR(-EINVAL); + + periph = kzalloc(sizeof(*periph), GFP_KERNEL); + if (!periph) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &peripheral_ops; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + init.flags = 0; + + periph->id = id; + periph->hw.init = &init; + periph->pmc = pmc; + + clk = clk_register(NULL, &periph->hw); + if (IS_ERR(clk)) + kfree(periph); + + return clk; +} + +static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph) +{ + struct clk *parent; + unsigned long parent_rate; + int shift = 0; + + if (!periph->auto_div) + return; + + if (periph->range.max) { + parent = clk_get_parent_by_index(periph->hw.clk, 0); + parent_rate = __clk_get_rate(parent); + if (!parent_rate) + return; + + for (; shift < PERIPHERAL_MAX_SHIFT; shift++) { + if (parent_rate >> shift <= periph->range.max) + break; + } + } + + periph->auto_div = false; + periph->div = shift; +} + +static int clk_sam9x5_peripheral_enable(struct clk_hw *hw) +{ + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + + if (periph->id < PERIPHERAL_ID_MIN) + return 0; + + pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) | + AT91_PMC_PCR_CMD | + AT91_PMC_PCR_DIV(periph->div) | + AT91_PMC_PCR_EN); + return 0; +} + +static void clk_sam9x5_peripheral_disable(struct clk_hw *hw) +{ + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + + if (periph->id < PERIPHERAL_ID_MIN) + return; + + pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) | + AT91_PMC_PCR_CMD); +} + +static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw) +{ + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + int ret; + + if (periph->id < PERIPHERAL_ID_MIN) + return 1; + + pmc_lock(pmc); + pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID)); + ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN); + pmc_unlock(pmc); + + return ret; +} + +static unsigned long +clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + struct at91_pmc *pmc = periph->pmc; + u32 tmp; + + if (periph->id < PERIPHERAL_ID_MIN) + return parent_rate; + + pmc_lock(pmc); + pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID)); + tmp = pmc_read(pmc, AT91_PMC_PCR); + pmc_unlock(pmc); + + if (tmp & AT91_PMC_PCR_EN) { + periph->div = PERIPHERAL_RSHIFT(tmp); + periph->auto_div = false; + } else { + clk_sam9x5_peripheral_autodiv(periph); + } + + return parent_rate >> periph->div; +} + +static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + int shift = 0; + unsigned long best_rate; + unsigned long best_diff; + unsigned long cur_rate = *parent_rate; + unsigned long cur_diff; + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + + if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) + return *parent_rate; + + if (periph->range.max) { + for (; shift < PERIPHERAL_MAX_SHIFT; shift++) { + cur_rate = *parent_rate >> shift; + if (cur_rate <= periph->range.max) + break; + } + } + + if (rate >= cur_rate) + return cur_rate; + + best_diff = cur_rate - rate; + best_rate = cur_rate; + for (; shift < PERIPHERAL_MAX_SHIFT; shift++) { + cur_rate = *parent_rate >> shift; + if (cur_rate < rate) + cur_diff = rate - cur_rate; + else + cur_diff = cur_rate - rate; + + if (cur_diff < best_diff) { + best_diff = cur_diff; + best_rate = cur_rate; + } + + if (!best_diff || cur_rate < rate) + break; + } + + return best_rate; +} + +static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + int shift; + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); + if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) { + if (parent_rate == rate) + return 0; + else + return -EINVAL; + } + + if (periph->range.max && rate > periph->range.max) + return -EINVAL; + + for (shift = 0; shift < PERIPHERAL_MAX_SHIFT; shift++) { + if (parent_rate >> shift == rate) { + periph->auto_div = false; + periph->div = shift; + return 0; + } + } + + return -EINVAL; +} + +static const struct clk_ops sam9x5_peripheral_ops = { + .enable = clk_sam9x5_peripheral_enable, + .disable = clk_sam9x5_peripheral_disable, + .is_enabled = clk_sam9x5_peripheral_is_enabled, + .recalc_rate = clk_sam9x5_peripheral_recalc_rate, + .round_rate = clk_sam9x5_peripheral_round_rate, + .set_rate = clk_sam9x5_peripheral_set_rate, +}; + +static struct clk * __init +at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, + const char *parent_name, u32 id, + const struct clk_range *range) +{ + struct clk_sam9x5_peripheral *periph; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !name || !parent_name) + return ERR_PTR(-EINVAL); + + periph = kzalloc(sizeof(*periph), GFP_KERNEL); + if (!periph) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &sam9x5_peripheral_ops; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + init.flags = 0; + + periph->id = id; + periph->hw.init = &init; + periph->div = 0; + periph->pmc = pmc; + periph->auto_div = true; + periph->range = *range; + + clk = clk_register(NULL, &periph->hw); + if (IS_ERR(clk)) + kfree(periph); + else + clk_sam9x5_peripheral_autodiv(periph); + + return clk; +} + +static void __init +of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) +{ + int num; + u32 id; + struct clk *clk; + const char *parent_name; + const char *name; + struct device_node *periphclknp; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) + return; + + num = of_get_child_count(np); + if (!num || num > PERIPHERAL_MAX) + return; + + for_each_child_of_node(np, periphclknp) { + if (of_property_read_u32(periphclknp, "reg", &id)) + continue; + + if (id >= PERIPHERAL_MAX) + continue; + + if (of_property_read_string(np, "clock-output-names", &name)) + name = periphclknp->name; + + if (type == PERIPHERAL_AT91RM9200) { + clk = at91_clk_register_peripheral(pmc, name, + parent_name, id); + } else { + struct clk_range range = CLK_RANGE(0, 0); + + of_at91_get_clk_range(periphclknp, + "atmel,clk-output-range", + &range); + + clk = at91_clk_register_sam9x5_peripheral(pmc, name, + parent_name, + id, &range); + } + + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(periphclknp, of_clk_src_simple_get, clk); + } +} + +void __init of_at91rm9200_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91RM9200); +} + +void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91SAM9X5); +} diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c new file mode 100644 index 000000000000..cf6ed023504c --- /dev/null +++ b/drivers/clk/at91/clk-pll.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/io.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include "pmc.h" + +#define PLL_STATUS_MASK(id) (1 << (1 + (id))) +#define PLL_REG(id) (AT91_CKGR_PLLAR + ((id) * 4)) +#define PLL_DIV_MASK 0xff +#define PLL_DIV_MAX PLL_DIV_MASK +#define PLL_DIV(reg) ((reg) & PLL_DIV_MASK) +#define PLL_MUL(reg, layout) (((reg) >> (layout)->mul_shift) & \ + (layout)->mul_mask) +#define PLL_ICPR_SHIFT(id) ((id) * 16) +#define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id)) +#define PLL_MAX_COUNT 0x3ff +#define PLL_COUNT_SHIFT 8 +#define PLL_OUT_SHIFT 14 +#define PLL_MAX_ID 1 + +struct clk_pll_characteristics { + struct clk_range input; + int num_output; + struct clk_range *output; + u16 *icpll; + u8 *out; +}; + +struct clk_pll_layout { + u32 pllr_mask; + u16 mul_mask; + u8 mul_shift; +}; + +#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw) + +struct clk_pll { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + u8 id; + u8 div; + u8 range; + u16 mul; + const struct clk_pll_layout *layout; + const struct clk_pll_characteristics *characteristics; +}; + +static irqreturn_t clk_pll_irq_handler(int irq, void *dev_id) +{ + struct clk_pll *pll = (struct clk_pll *)dev_id; + + wake_up(&pll->wait); + disable_irq_nosync(pll->irq); + + return IRQ_HANDLED; +} + +static int clk_pll_prepare(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct at91_pmc *pmc = pll->pmc; + const struct clk_pll_layout *layout = pll->layout; + const struct clk_pll_characteristics *characteristics = + pll->characteristics; + u8 id = pll->id; + u32 mask = PLL_STATUS_MASK(id); + int offset = PLL_REG(id); + u8 out = 0; + u32 pllr, icpr; + u8 div; + u16 mul; + + pllr = pmc_read(pmc, offset); + div = PLL_DIV(pllr); + mul = PLL_MUL(pllr, layout); + + if ((pmc_read(pmc, AT91_PMC_SR) & mask) && + (div == pll->div && mul == pll->mul)) + return 0; + + if (characteristics->out) + out = characteristics->out[pll->range]; + if (characteristics->icpll) { + icpr = pmc_read(pmc, AT91_PMC_PLLICPR) & ~PLL_ICPR_MASK(id); + icpr |= (characteristics->icpll[pll->range] << + PLL_ICPR_SHIFT(id)); + pmc_write(pmc, AT91_PMC_PLLICPR, icpr); + } + + pllr &= ~layout->pllr_mask; + pllr |= layout->pllr_mask & + (pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | + (out << PLL_OUT_SHIFT) | + ((pll->mul & layout->mul_mask) << layout->mul_shift)); + pmc_write(pmc, offset, pllr); + + while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { + enable_irq(pll->irq); + wait_event(pll->wait, + pmc_read(pmc, AT91_PMC_SR) & mask); + } + + return 0; +} + +static int clk_pll_is_prepared(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct at91_pmc *pmc = pll->pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) & + PLL_STATUS_MASK(pll->id)); +} + +static void clk_pll_unprepare(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct at91_pmc *pmc = pll->pmc; + const struct clk_pll_layout *layout = pll->layout; + int offset = PLL_REG(pll->id); + u32 tmp = pmc_read(pmc, offset) & ~(layout->pllr_mask); + + pmc_write(pmc, offset, tmp); +} + +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_pll *pll = to_clk_pll(hw); + const struct clk_pll_layout *layout = pll->layout; + struct at91_pmc *pmc = pll->pmc; + int offset = PLL_REG(pll->id); + u32 tmp = pmc_read(pmc, offset) & layout->pllr_mask; + u8 div = PLL_DIV(tmp); + u16 mul = PLL_MUL(tmp, layout); + if (!div || !mul) + return 0; + + return (parent_rate * (mul + 1)) / div; +} + +static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, + unsigned long parent_rate, + u32 *div, u32 *mul, + u32 *index) { + unsigned long maxrate; + unsigned long minrate; + unsigned long divrate; + unsigned long bestdiv = 1; + unsigned long bestmul; + unsigned long tmpdiv; + unsigned long roundup; + unsigned long rounddown; + unsigned long remainder; + unsigned long bestremainder; + unsigned long maxmul; + unsigned long maxdiv; + unsigned long mindiv; + int i = 0; + const struct clk_pll_layout *layout = pll->layout; + const struct clk_pll_characteristics *characteristics = + pll->characteristics; + + /* Minimum divider = 1 */ + /* Maximum multiplier = max_mul */ + maxmul = layout->mul_mask + 1; + maxrate = (parent_rate * maxmul) / 1; + + /* Maximum divider = max_div */ + /* Minimum multiplier = 2 */ + maxdiv = PLL_DIV_MAX; + minrate = (parent_rate * 2) / maxdiv; + + if (parent_rate < characteristics->input.min || + parent_rate < characteristics->input.max) + return -ERANGE; + + if (parent_rate < minrate || parent_rate > maxrate) + return -ERANGE; + + for (i = 0; i < characteristics->num_output; i++) { + if (parent_rate >= characteristics->output[i].min && + parent_rate <= characteristics->output[i].max) + break; + } + + if (i >= characteristics->num_output) + return -ERANGE; + + bestmul = rate / parent_rate; + rounddown = parent_rate % rate; + roundup = rate - rounddown; + bestremainder = roundup < rounddown ? roundup : rounddown; + + if (!bestremainder) { + if (div) + *div = bestdiv; + if (mul) + *mul = bestmul; + if (index) + *index = i; + return rate; + } + + maxdiv = 255 / (bestmul + 1); + if (parent_rate / maxdiv < characteristics->input.min) + maxdiv = parent_rate / characteristics->input.min; + mindiv = parent_rate / characteristics->input.max; + if (parent_rate % characteristics->input.max) + mindiv++; + + for (tmpdiv = mindiv; tmpdiv < maxdiv; tmpdiv++) { + divrate = parent_rate / tmpdiv; + + rounddown = rate % divrate; + roundup = divrate - rounddown; + remainder = roundup < rounddown ? roundup : rounddown; + + if (remainder < bestremainder) { + bestremainder = remainder; + bestmul = rate / divrate; + bestdiv = tmpdiv; + } + + if (!remainder) + break; + } + + rate = (parent_rate / bestdiv) * bestmul; + + if (div) + *div = bestdiv; + if (mul) + *mul = bestmul; + if (index) + *index = i; + + return rate; +} + +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct clk_pll *pll = to_clk_pll(hw); + + return clk_pll_get_best_div_mul(pll, rate, *parent_rate, + NULL, NULL, NULL); +} + +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_pll *pll = to_clk_pll(hw); + long ret; + u32 div; + u32 mul; + u32 index; + + ret = clk_pll_get_best_div_mul(pll, rate, parent_rate, + &div, &mul, &index); + if (ret < 0) + return ret; + + pll->range = index; + pll->div = div; + pll->mul = mul; + + return 0; +} + +static const struct clk_ops pll_ops = { + .prepare = clk_pll_prepare, + .unprepare = clk_pll_unprepare, + .is_prepared = clk_pll_is_prepared, + .recalc_rate = clk_pll_recalc_rate, + .round_rate = clk_pll_round_rate, + .set_rate = clk_pll_set_rate, +}; + +static struct clk * __init +at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, + const char *parent_name, u8 id, + const struct clk_pll_layout *layout, + const struct clk_pll_characteristics *characteristics) +{ + struct clk_pll *pll; + struct clk *clk = NULL; + struct clk_init_data init; + int ret; + int offset = PLL_REG(id); + u32 tmp; + + if (id > PLL_MAX_ID) + return ERR_PTR(-EINVAL); + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &pll_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_GATE; + + pll->id = id; + pll->hw.init = &init; + pll->layout = layout; + pll->characteristics = characteristics; + pll->pmc = pmc; + pll->irq = irq; + tmp = pmc_read(pmc, offset) & layout->pllr_mask; + pll->div = PLL_DIV(tmp); + pll->mul = PLL_MUL(tmp, layout); + init_waitqueue_head(&pll->wait); + irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); + ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, + id ? "clk-pllb" : "clk-plla", pll); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + + +static const struct clk_pll_layout at91rm9200_pll_layout = { + .pllr_mask = 0x7FFFFFF, + .mul_shift = 16, + .mul_mask = 0x7FF, +}; + +static const struct clk_pll_layout at91sam9g45_pll_layout = { + .pllr_mask = 0xFFFFFF, + .mul_shift = 16, + .mul_mask = 0xFF, +}; + +static const struct clk_pll_layout at91sam9g20_pllb_layout = { + .pllr_mask = 0x3FFFFF, + .mul_shift = 16, + .mul_mask = 0x3F, +}; + +static const struct clk_pll_layout sama5d3_pll_layout = { + .pllr_mask = 0x1FFFFFF, + .mul_shift = 18, + .mul_mask = 0x7F, +}; + + +static struct clk_pll_characteristics * __init +of_at91_clk_pll_get_characteristics(struct device_node *np) +{ + int i; + int offset; + u32 tmp; + int num_output; + u32 num_cells; + struct clk_range input; + struct clk_range *output; + u8 *out = NULL; + u16 *icpll = NULL; + struct clk_pll_characteristics *characteristics; + + if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input)) + return NULL; + + if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells", + &num_cells)) + return NULL; + + if (num_cells < 2 || num_cells > 4) + return NULL; + + if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp)) + return NULL; + num_output = tmp / (sizeof(u32) * num_cells); + + characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL); + if (!characteristics) + return NULL; + + output = kzalloc(sizeof(*output) * num_output, GFP_KERNEL); + if (!output) + goto out_free_characteristics; + + if (num_cells > 2) { + out = kzalloc(sizeof(*out) * num_output, GFP_KERNEL); + if (!out) + goto out_free_output; + } + + if (num_cells > 3) { + icpll = kzalloc(sizeof(*icpll) * num_output, GFP_KERNEL); + if (!icpll) + goto out_free_output; + } + + for (i = 0; i < num_output; i++) { + offset = i * num_cells; + if (of_property_read_u32_index(np, + "atmel,pll-clk-output-ranges", + offset, &tmp)) + goto out_free_output; + output[i].min = tmp; + if (of_property_read_u32_index(np, + "atmel,pll-clk-output-ranges", + offset + 1, &tmp)) + goto out_free_output; + output[i].max = tmp; + + if (num_cells == 2) + continue; + + if (of_property_read_u32_index(np, + "atmel,pll-clk-output-ranges", + offset + 2, &tmp)) + goto out_free_output; + out[i] = tmp; + + if (num_cells == 3) + continue; + + if (of_property_read_u32_index(np, + "atmel,pll-clk-output-ranges", + offset + 3, &tmp)) + goto out_free_output; + icpll[i] = tmp; + } + + characteristics->input = input; + characteristics->num_output = num_output; + characteristics->output = output; + characteristics->out = out; + characteristics->icpll = icpll; + return characteristics; + +out_free_output: + kfree(icpll); + kfree(out); + kfree(output); +out_free_characteristics: + kfree(characteristics); + return NULL; +} + +static void __init +of_at91_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc, + const struct clk_pll_layout *layout) +{ + u32 id; + unsigned int irq; + struct clk *clk; + const char *parent_name; + const char *name = np->name; + struct clk_pll_characteristics *characteristics; + + if (of_property_read_u32(np, "reg", &id)) + return; + + parent_name = of_clk_get_parent_name(np, 0); + + of_property_read_string(np, "clock-output-names", &name); + + characteristics = of_at91_clk_pll_get_characteristics(np); + if (!characteristics) + return; + + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_pll(pmc, irq, name, parent_name, id, layout, + characteristics); + if (IS_ERR(clk)) + goto out_free_characteristics; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; + +out_free_characteristics: + kfree(characteristics); +} + +void __init of_at91rm9200_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_pll_setup(np, pmc, &at91rm9200_pll_layout); +} + +void __init of_at91sam9g45_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_pll_setup(np, pmc, &at91sam9g45_pll_layout); +} + +void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_pll_setup(np, pmc, &at91sam9g20_pllb_layout); +} + +void __init of_sama5d3_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_pll_setup(np, pmc, &sama5d3_pll_layout); +} diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c new file mode 100644 index 000000000000..ea226562bb40 --- /dev/null +++ b/drivers/clk/at91/clk-plldiv.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> + +#include "pmc.h" + +#define to_clk_plldiv(hw) container_of(hw, struct clk_plldiv, hw) + +struct clk_plldiv { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +static unsigned long clk_plldiv_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_plldiv *plldiv = to_clk_plldiv(hw); + struct at91_pmc *pmc = plldiv->pmc; + + if (pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_PLLADIV2) + return parent_rate / 2; + + return parent_rate; +} + +static long clk_plldiv_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + + if (rate > *parent_rate) + return *parent_rate; + div = *parent_rate / 2; + if (rate < div) + return div; + + if (rate - div < *parent_rate - rate) + return div; + + return *parent_rate; +} + +static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_plldiv *plldiv = to_clk_plldiv(hw); + struct at91_pmc *pmc = plldiv->pmc; + u32 tmp; + + if (parent_rate != rate && (parent_rate / 2) != rate) + return -EINVAL; + + pmc_lock(pmc); + tmp = pmc_read(pmc, AT91_PMC_MCKR) & ~AT91_PMC_PLLADIV2; + if ((parent_rate / 2) == rate) + tmp |= AT91_PMC_PLLADIV2; + pmc_write(pmc, AT91_PMC_MCKR, tmp); + pmc_unlock(pmc); + + return 0; +} + +static const struct clk_ops plldiv_ops = { + .recalc_rate = clk_plldiv_recalc_rate, + .round_rate = clk_plldiv_round_rate, + .set_rate = clk_plldiv_set_rate, +}; + +static struct clk * __init +at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name, + const char *parent_name) +{ + struct clk_plldiv *plldiv; + struct clk *clk = NULL; + struct clk_init_data init; + + plldiv = kzalloc(sizeof(*plldiv), GFP_KERNEL); + if (!plldiv) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &plldiv_ops; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.flags = CLK_SET_RATE_GATE; + + plldiv->hw.init = &init; + plldiv->pmc = pmc; + + clk = clk_register(NULL, &plldiv->hw); + + if (IS_ERR(clk)) + kfree(plldiv); + + return clk; +} + +static void __init +of_at91_clk_plldiv_setup(struct device_node *np, struct at91_pmc *pmc) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + + parent_name = of_clk_get_parent_name(np, 0); + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91_clk_register_plldiv(pmc, name, parent_name); + + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; +} + +void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_plldiv_setup(np, pmc); +} diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c new file mode 100644 index 000000000000..fd792b203eaf --- /dev/null +++ b/drivers/clk/at91/clk-programmable.c @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/io.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include "pmc.h" + +#define PROG_SOURCE_MAX 5 +#define PROG_ID_MAX 7 + +#define PROG_STATUS_MASK(id) (1 << ((id) + 8)) +#define PROG_PRES_MASK 0x7 +#define PROG_MAX_RM9200_CSS 3 + +struct clk_programmable_layout { + u8 pres_shift; + u8 css_mask; + u8 have_slck_mck; +}; + +struct clk_programmable { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + u8 id; + u8 css; + u8 pres; + u8 slckmck; + const struct clk_programmable_layout *layout; +}; + +#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw) + + +static irqreturn_t clk_programmable_irq_handler(int irq, void *dev_id) +{ + struct clk_programmable *prog = (struct clk_programmable *)dev_id; + + wake_up(&prog->wait); + + return IRQ_HANDLED; +} + +static int clk_programmable_prepare(struct clk_hw *hw) +{ + u32 tmp; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog->pmc; + const struct clk_programmable_layout *layout = prog->layout; + u8 id = prog->id; + u32 mask = PROG_STATUS_MASK(id); + + tmp = prog->css | (prog->pres << layout->pres_shift); + if (layout->have_slck_mck && prog->slckmck) + tmp |= AT91_PMC_CSSMCK_MCK; + + pmc_write(pmc, AT91_PMC_PCKR(id), tmp); + + while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) + wait_event(prog->wait, pmc_read(pmc, AT91_PMC_SR) & mask); + + return 0; +} + +static int clk_programmable_is_ready(struct clk_hw *hw) +{ + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog->pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_PCKR(prog->id)); +} + +static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog->pmc; + const struct clk_programmable_layout *layout = prog->layout; + + tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); + prog->pres = (tmp >> layout->pres_shift) & PROG_PRES_MASK; + + return parent_rate >> prog->pres; +} + +static long clk_programmable_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long best_rate = *parent_rate; + unsigned long best_diff; + unsigned long new_diff; + unsigned long cur_rate; + int shift = shift; + + if (rate > *parent_rate) + return *parent_rate; + else + best_diff = *parent_rate - rate; + + if (!best_diff) + return best_rate; + + for (shift = 1; shift < PROG_PRES_MASK; shift++) { + cur_rate = *parent_rate >> shift; + + if (cur_rate > rate) + new_diff = cur_rate - rate; + else + new_diff = rate - cur_rate; + + if (!new_diff) + return cur_rate; + + if (new_diff < best_diff) { + best_diff = new_diff; + best_rate = cur_rate; + } + + if (rate > cur_rate) + break; + } + + return best_rate; +} + +static int clk_programmable_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_programmable *prog = to_clk_programmable(hw); + const struct clk_programmable_layout *layout = prog->layout; + if (index > layout->css_mask) { + if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { + prog->css = 0; + prog->slckmck = 1; + return 0; + } else { + return -EINVAL; + } + } + + prog->css = index; + return 0; +} + +static u8 clk_programmable_get_parent(struct clk_hw *hw) +{ + u32 tmp; + u8 ret; + struct clk_programmable *prog = to_clk_programmable(hw); + struct at91_pmc *pmc = prog->pmc; + const struct clk_programmable_layout *layout = prog->layout; + + tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); + prog->css = tmp & layout->css_mask; + ret = prog->css; + if (layout->have_slck_mck) { + prog->slckmck = !!(tmp & AT91_PMC_CSSMCK_MCK); + if (prog->slckmck && !ret) + ret = PROG_MAX_RM9200_CSS + 1; + } + + return ret; +} + +static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_programmable *prog = to_clk_programmable(hw); + unsigned long best_rate = parent_rate; + unsigned long best_diff; + unsigned long new_diff; + unsigned long cur_rate; + int shift = 0; + + if (rate > parent_rate) + return parent_rate; + else + best_diff = parent_rate - rate; + + if (!best_diff) { + prog->pres = shift; + return 0; + } + + for (shift = 1; shift < PROG_PRES_MASK; shift++) { + cur_rate = parent_rate >> shift; + + if (cur_rate > rate) + new_diff = cur_rate - rate; + else + new_diff = rate - cur_rate; + + if (!new_diff) + break; + + if (new_diff < best_diff) { + best_diff = new_diff; + best_rate = cur_rate; + } + + if (rate > cur_rate) + break; + } + + prog->pres = shift; + return 0; +} + +static const struct clk_ops programmable_ops = { + .prepare = clk_programmable_prepare, + .is_prepared = clk_programmable_is_ready, + .recalc_rate = clk_programmable_recalc_rate, + .round_rate = clk_programmable_round_rate, + .get_parent = clk_programmable_get_parent, + .set_parent = clk_programmable_set_parent, + .set_rate = clk_programmable_set_rate, +}; + +static struct clk * __init +at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq, + const char *name, const char **parent_names, + u8 num_parents, u8 id, + const struct clk_programmable_layout *layout) +{ + int ret; + struct clk_programmable *prog; + struct clk *clk = NULL; + struct clk_init_data init; + char irq_name[11]; + + if (id > PROG_ID_MAX) + return ERR_PTR(-EINVAL); + + prog = kzalloc(sizeof(*prog), GFP_KERNEL); + if (!prog) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &programmable_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + prog->id = id; + prog->layout = layout; + prog->hw.init = &init; + prog->pmc = pmc; + prog->irq = irq; + init_waitqueue_head(&prog->wait); + irq_set_status_flags(prog->irq, IRQ_NOAUTOEN); + snprintf(irq_name, sizeof(irq_name), "clk-prog%d", id); + ret = request_irq(prog->irq, clk_programmable_irq_handler, + IRQF_TRIGGER_HIGH, irq_name, prog); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &prog->hw); + if (IS_ERR(clk)) + kfree(prog); + + return clk; +} + +static const struct clk_programmable_layout at91rm9200_programmable_layout = { + .pres_shift = 2, + .css_mask = 0x3, + .have_slck_mck = 0, +}; + +static const struct clk_programmable_layout at91sam9g45_programmable_layout = { + .pres_shift = 2, + .css_mask = 0x3, + .have_slck_mck = 1, +}; + +static const struct clk_programmable_layout at91sam9x5_programmable_layout = { + .pres_shift = 4, + .css_mask = 0x7, + .have_slck_mck = 0, +}; + +static void __init +of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, + const struct clk_programmable_layout *layout) +{ + int num; + u32 id; + int i; + unsigned int irq; + struct clk *clk; + int num_parents; + const char *parent_names[PROG_SOURCE_MAX]; + const char *name; + struct device_node *progclknp; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX) + return; + + for (i = 0; i < num_parents; ++i) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + num = of_get_child_count(np); + if (!num || num > (PROG_ID_MAX + 1)) + return; + + for_each_child_of_node(np, progclknp) { + if (of_property_read_u32(progclknp, "reg", &id)) + continue; + + if (of_property_read_string(np, "clock-output-names", &name)) + name = progclknp->name; + + irq = irq_of_parse_and_map(progclknp, 0); + if (!irq) + continue; + + clk = at91_clk_register_programmable(pmc, irq, name, + parent_names, num_parents, + id, layout); + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(progclknp, of_clk_src_simple_get, clk); + } +} + + +void __init of_at91rm9200_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_prog_setup(np, pmc, &at91rm9200_programmable_layout); +} + +void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_prog_setup(np, pmc, &at91sam9g45_programmable_layout); +} + +void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_prog_setup(np, pmc, &at91sam9x5_programmable_layout); +} diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c new file mode 100644 index 000000000000..144d47ecfe63 --- /dev/null +++ b/drivers/clk/at91/clk-smd.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> + +#include "pmc.h" + +#define SMD_SOURCE_MAX 2 + +#define SMD_DIV_SHIFT 8 +#define SMD_MAX_DIV 0xf + +struct at91sam9x5_clk_smd { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_smd(hw) \ + container_of(hw, struct at91sam9x5_clk_smd, hw) + +static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 smddiv; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd->pmc; + + tmp = pmc_read(pmc, AT91_PMC_SMD); + smddiv = (tmp & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT; + return parent_rate / (smddiv + 1); +} + +static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + unsigned long bestrate; + unsigned long tmp; + + if (rate >= *parent_rate) + return *parent_rate; + + div = *parent_rate / rate; + if (div > SMD_MAX_DIV) + return *parent_rate / (SMD_MAX_DIV + 1); + + bestrate = *parent_rate / div; + tmp = *parent_rate / (div + 1); + if (bestrate - rate > rate - tmp) + bestrate = tmp; + + return bestrate; +} + +static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd->pmc; + + if (index > 1) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMDS; + if (index) + tmp |= AT91_PMC_SMDS; + pmc_write(pmc, AT91_PMC_SMD, tmp); + return 0; +} + +static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw) +{ + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd->pmc; + + return pmc_read(pmc, AT91_PMC_SMD) & AT91_PMC_SMDS; +} + +static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); + struct at91_pmc *pmc = smd->pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate || div < 1 || div > (SMD_MAX_DIV + 1)) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMD_DIV; + tmp |= (div - 1) << SMD_DIV_SHIFT; + pmc_write(pmc, AT91_PMC_SMD, tmp); + + return 0; +} + +static const struct clk_ops at91sam9x5_smd_ops = { + .recalc_rate = at91sam9x5_clk_smd_recalc_rate, + .round_rate = at91sam9x5_clk_smd_round_rate, + .get_parent = at91sam9x5_clk_smd_get_parent, + .set_parent = at91sam9x5_clk_smd_set_parent, + .set_rate = at91sam9x5_clk_smd_set_rate, +}; + +static struct clk * __init +at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name, + const char **parent_names, u8 num_parents) +{ + struct at91sam9x5_clk_smd *smd; + struct clk *clk = NULL; + struct clk_init_data init; + + smd = kzalloc(sizeof(*smd), GFP_KERNEL); + if (!smd) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &at91sam9x5_smd_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + smd->hw.init = &init; + smd->pmc = pmc; + + clk = clk_register(NULL, &smd->hw); + if (IS_ERR(clk)) + kfree(smd); + + return clk; +} + +void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + int i; + int num_parents; + const char *parent_names[SMD_SOURCE_MAX]; + const char *name = np->name; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX) + return; + + for (i = 0; i < num_parents; i++) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91sam9x5_clk_register_smd(pmc, name, parent_names, + num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c new file mode 100644 index 000000000000..8f7c0434a09f --- /dev/null +++ b/drivers/clk/at91/clk-system.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> + +#include "pmc.h" + +#define SYSTEM_MAX_ID 31 + +#define SYSTEM_MAX_NAME_SZ 32 + +#define to_clk_system(hw) container_of(hw, struct clk_system, hw) +struct clk_system { + struct clk_hw hw; + struct at91_pmc *pmc; + u8 id; +}; + +static int clk_system_enable(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys->pmc; + + pmc_write(pmc, AT91_PMC_SCER, 1 << sys->id); + return 0; +} + +static void clk_system_disable(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys->pmc; + + pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id); +} + +static int clk_system_is_enabled(struct clk_hw *hw) +{ + struct clk_system *sys = to_clk_system(hw); + struct at91_pmc *pmc = sys->pmc; + + return !!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id)); +} + +static const struct clk_ops system_ops = { + .enable = clk_system_enable, + .disable = clk_system_disable, + .is_enabled = clk_system_is_enabled, +}; + +static struct clk * __init +at91_clk_register_system(struct at91_pmc *pmc, const char *name, + const char *parent_name, u8 id) +{ + struct clk_system *sys; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!parent_name || id > SYSTEM_MAX_ID) + return ERR_PTR(-EINVAL); + + sys = kzalloc(sizeof(*sys), GFP_KERNEL); + if (!sys) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &system_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + /* + * CLK_IGNORE_UNUSED is used to avoid ddrck switch off. + * TODO : we should implement a driver supporting at91 ddr controller + * (see drivers/memory) which would request and enable the ddrck clock. + * When this is done we will be able to remove CLK_IGNORE_UNUSED flag. + */ + init.flags = CLK_IGNORE_UNUSED; + + sys->id = id; + sys->hw.init = &init; + sys->pmc = pmc; + + clk = clk_register(NULL, &sys->hw); + if (IS_ERR(clk)) + kfree(sys); + + return clk; +} + +static void __init +of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) +{ + int num; + u32 id; + struct clk *clk; + const char *name; + struct device_node *sysclknp; + const char *parent_name; + + num = of_get_child_count(np); + if (num > (SYSTEM_MAX_ID + 1)) + return; + + for_each_child_of_node(np, sysclknp) { + if (of_property_read_u32(sysclknp, "reg", &id)) + continue; + + if (of_property_read_string(np, "clock-output-names", &name)) + name = sysclknp->name; + + parent_name = of_clk_get_parent_name(sysclknp, 0); + + clk = at91_clk_register_system(pmc, name, parent_name, id); + if (IS_ERR(clk)) + continue; + + of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk); + } +} + +void __init of_at91rm9200_clk_sys_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_sys_setup(np, pmc); +} diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c new file mode 100644 index 000000000000..7d1d26a4bd04 --- /dev/null +++ b/drivers/clk/at91/clk-usb.c @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> + +#include "pmc.h" + +#define USB_SOURCE_MAX 2 + +#define SAM9X5_USB_DIV_SHIFT 8 +#define SAM9X5_USB_MAX_DIV 0xf + +#define RM9200_USB_DIV_SHIFT 28 +#define RM9200_USB_DIV_TAB_SIZE 4 + +struct at91sam9x5_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_at91sam9x5_clk_usb(hw) \ + container_of(hw, struct at91sam9x5_clk_usb, hw) + +struct at91rm9200_clk_usb { + struct clk_hw hw; + struct at91_pmc *pmc; + u32 divisors[4]; +}; + +#define to_at91rm9200_clk_usb(hw) \ + container_of(hw, struct at91rm9200_clk_usb, hw) + +static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 tmp; + u8 usbdiv; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + tmp = pmc_read(pmc, AT91_PMC_USB); + usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; + return parent_rate / (usbdiv + 1); +} + +static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long div; + unsigned long bestrate; + unsigned long tmp; + + if (rate >= *parent_rate) + return *parent_rate; + + div = *parent_rate / rate; + if (div >= SAM9X5_USB_MAX_DIV) + return *parent_rate / (SAM9X5_USB_MAX_DIV + 1); + + bestrate = *parent_rate / div; + tmp = *parent_rate / (div + 1); + if (bestrate - rate > rate - tmp) + bestrate = tmp; + + return bestrate; +} + +static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) +{ + u32 tmp; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + if (index > 1) + return -EINVAL; + tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS; + if (index) + tmp |= AT91_PMC_USBS; + pmc_write(pmc, AT91_PMC_USB, tmp); + return 0; +} + +static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw) +{ + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + return pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS; +} + +static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate || div < 1 || div >= SAM9X5_USB_MAX_DIV) + return -EINVAL; + + tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV; + tmp |= (div - 1) << SAM9X5_USB_DIV_SHIFT; + pmc_write(pmc, AT91_PMC_USB, tmp); + + return 0; +} + +static const struct clk_ops at91sam9x5_usb_ops = { + .recalc_rate = at91sam9x5_clk_usb_recalc_rate, + .round_rate = at91sam9x5_clk_usb_round_rate, + .get_parent = at91sam9x5_clk_usb_get_parent, + .set_parent = at91sam9x5_clk_usb_set_parent, + .set_rate = at91sam9x5_clk_usb_set_rate, +}; + +static int at91sam9n12_clk_usb_enable(struct clk_hw *hw) +{ + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + pmc_write(pmc, AT91_PMC_USB, + pmc_read(pmc, AT91_PMC_USB) | AT91_PMC_USBS); + return 0; +} + +static void at91sam9n12_clk_usb_disable(struct clk_hw *hw) +{ + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + pmc_write(pmc, AT91_PMC_USB, + pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS); +} + +static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw) +{ + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + + return !!(pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS); +} + +static const struct clk_ops at91sam9n12_usb_ops = { + .enable = at91sam9n12_clk_usb_enable, + .disable = at91sam9n12_clk_usb_disable, + .is_enabled = at91sam9n12_clk_usb_is_enabled, + .recalc_rate = at91sam9x5_clk_usb_recalc_rate, + .round_rate = at91sam9x5_clk_usb_round_rate, + .set_rate = at91sam9x5_clk_usb_set_rate, +}; + +static struct clk * __init +at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name, + const char **parent_names, u8 num_parents) +{ + struct at91sam9x5_clk_usb *usb; + struct clk *clk = NULL; + struct clk_init_data init; + + usb = kzalloc(sizeof(*usb), GFP_KERNEL); + if (!usb) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &at91sam9x5_usb_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + usb->hw.init = &init; + usb->pmc = pmc; + + clk = clk_register(NULL, &usb->hw); + if (IS_ERR(clk)) + kfree(usb); + + return clk; +} + +static struct clk * __init +at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name, + const char *parent_name) +{ + struct at91sam9x5_clk_usb *usb; + struct clk *clk = NULL; + struct clk_init_data init; + + usb = kzalloc(sizeof(*usb), GFP_KERNEL); + if (!usb) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &at91sam9n12_usb_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_GATE; + + usb->hw.init = &init; + usb->pmc = pmc; + + clk = clk_register(NULL, &usb->hw); + if (IS_ERR(clk)) + kfree(usb); + + return clk; +} + +static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + u32 tmp; + u8 usbdiv; + + tmp = pmc_read(pmc, AT91_CKGR_PLLBR); + usbdiv = (tmp & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT; + if (usb->divisors[usbdiv]) + return parent_rate / usb->divisors[usbdiv]; + + return 0; +} + +static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); + unsigned long bestrate = 0; + int bestdiff = -1; + unsigned long tmprate; + int tmpdiff; + int i = 0; + + for (i = 0; i < 4; i++) { + if (!usb->divisors[i]) + continue; + tmprate = *parent_rate / usb->divisors[i]; + if (tmprate < rate) + tmpdiff = rate - tmprate; + else + tmpdiff = tmprate - rate; + + if (bestdiff < 0 || bestdiff > tmpdiff) { + bestrate = tmprate; + bestdiff = tmpdiff; + } + + if (!bestdiff) + break; + } + + return bestrate; +} + +static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 tmp; + int i; + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); + struct at91_pmc *pmc = usb->pmc; + unsigned long div = parent_rate / rate; + + if (parent_rate % rate) + return -EINVAL; + for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { + if (usb->divisors[i] == div) { + tmp = pmc_read(pmc, AT91_CKGR_PLLBR) & + ~AT91_PMC_USBDIV; + tmp |= i << RM9200_USB_DIV_SHIFT; + pmc_write(pmc, AT91_CKGR_PLLBR, tmp); + return 0; + } + } + + return -EINVAL; +} + +static const struct clk_ops at91rm9200_usb_ops = { + .recalc_rate = at91rm9200_clk_usb_recalc_rate, + .round_rate = at91rm9200_clk_usb_round_rate, + .set_rate = at91rm9200_clk_usb_set_rate, +}; + +static struct clk * __init +at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name, + const char *parent_name, const u32 *divisors) +{ + struct at91rm9200_clk_usb *usb; + struct clk *clk = NULL; + struct clk_init_data init; + + usb = kzalloc(sizeof(*usb), GFP_KERNEL); + if (!usb) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &at91rm9200_usb_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = 0; + + usb->hw.init = &init; + usb->pmc = pmc; + memcpy(usb->divisors, divisors, sizeof(usb->divisors)); + + clk = clk_register(NULL, &usb->hw); + if (IS_ERR(clk)) + kfree(usb); + + return clk; +} + +void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + int i; + int num_parents; + const char *parent_names[USB_SOURCE_MAX]; + const char *name = np->name; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > USB_SOURCE_MAX) + return; + + for (i = 0; i < num_parents; i++) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91sam9x5_clk_register_usb(pmc, name, parent_names, num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) + return; + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91sam9n12_clk_register_usb(pmc, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +void __init of_at91rm9200_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + u32 divisors[4] = {0, 0, 0, 0}; + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) + return; + + of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4); + if (!divisors[0]) + return; + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91rm9200_clk_register_usb(pmc, name, parent_name, divisors); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c new file mode 100644 index 000000000000..ae3263bc1476 --- /dev/null +++ b/drivers/clk/at91/clk-utmi.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/io.h> +#include <linux/sched.h> +#include <linux/wait.h> + +#include "pmc.h" + +#define UTMI_FIXED_MUL 40 + +struct clk_utmi { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; +}; + +#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) + +static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id) +{ + struct clk_utmi *utmi = (struct clk_utmi *)dev_id; + + wake_up(&utmi->wait); + disable_irq_nosync(utmi->irq); + + return IRQ_HANDLED; +} + +static int clk_utmi_prepare(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi->pmc; + u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) | AT91_PMC_UPLLEN | + AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; + + pmc_write(pmc, AT91_CKGR_UCKR, tmp); + + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU)) { + enable_irq(utmi->irq); + wait_event(utmi->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); + } + + return 0; +} + +static int clk_utmi_is_prepared(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi->pmc; + + return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); +} + +static void clk_utmi_unprepare(struct clk_hw *hw) +{ + struct clk_utmi *utmi = to_clk_utmi(hw); + struct at91_pmc *pmc = utmi->pmc; + u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN; + + pmc_write(pmc, AT91_CKGR_UCKR, tmp); +} + +static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + /* UTMI clk is a fixed clk multiplier */ + return parent_rate * UTMI_FIXED_MUL; +} + +static const struct clk_ops utmi_ops = { + .prepare = clk_utmi_prepare, + .unprepare = clk_utmi_unprepare, + .is_prepared = clk_utmi_is_prepared, + .recalc_rate = clk_utmi_recalc_rate, +}; + +static struct clk * __init +at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, + const char *name, const char *parent_name) +{ + int ret; + struct clk_utmi *utmi; + struct clk *clk = NULL; + struct clk_init_data init; + + utmi = kzalloc(sizeof(*utmi), GFP_KERNEL); + if (!utmi) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &utmi_ops; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.flags = CLK_SET_RATE_GATE; + + utmi->hw.init = &init; + utmi->pmc = pmc; + utmi->irq = irq; + init_waitqueue_head(&utmi->wait); + irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); + ret = request_irq(utmi->irq, clk_utmi_irq_handler, + IRQF_TRIGGER_HIGH, "clk-utmi", utmi); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &utmi->hw); + if (IS_ERR(clk)) + kfree(utmi); + + return clk; +} + +static void __init +of_at91_clk_utmi_setup(struct device_node *np, struct at91_pmc *pmc) +{ + unsigned int irq; + struct clk *clk; + const char *parent_name; + const char *name = np->name; + + parent_name = of_clk_get_parent_name(np, 0); + + of_property_read_string(np, "clock-output-names", &name); + + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_utmi(pmc, irq, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + return; +} + +void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + of_at91_clk_utmi_setup(np, pmc); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c new file mode 100644 index 000000000000..7b9db603b936 --- /dev/null +++ b/drivers/clk/at91/pmc.c @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/irqdomain.h> +#include <linux/of_irq.h> + +#include <asm/proc-fns.h> + +#include "pmc.h" + +void __iomem *at91_pmc_base; +EXPORT_SYMBOL_GPL(at91_pmc_base); + +void at91sam9_idle(void) +{ + at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); + cpu_do_idle(); +} + +int of_at91_get_clk_range(struct device_node *np, const char *propname, + struct clk_range *range) +{ + u32 min, max; + int ret; + + ret = of_property_read_u32_index(np, propname, 0, &min); + if (ret) + return ret; + + ret = of_property_read_u32_index(np, propname, 1, &max); + if (ret) + return ret; + + if (range) { + range->min = min; + range->max = max; + } + + return 0; +} +EXPORT_SYMBOL_GPL(of_at91_get_clk_range); + +static void pmc_irq_mask(struct irq_data *d) +{ + struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); + + pmc_write(pmc, AT91_PMC_IDR, 1 << d->hwirq); +} + +static void pmc_irq_unmask(struct irq_data *d) +{ + struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); + + pmc_write(pmc, AT91_PMC_IER, 1 << d->hwirq); +} + +static int pmc_irq_set_type(struct irq_data *d, unsigned type) +{ + if (type != IRQ_TYPE_LEVEL_HIGH) { + pr_warn("PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n"); + return -EINVAL; + } + + return 0; +} + +static struct irq_chip pmc_irq = { + .name = "PMC", + .irq_disable = pmc_irq_mask, + .irq_mask = pmc_irq_mask, + .irq_unmask = pmc_irq_unmask, + .irq_set_type = pmc_irq_set_type, +}; + +static struct lock_class_key pmc_lock_class; + +static int pmc_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct at91_pmc *pmc = h->host_data; + + irq_set_lockdep_class(virq, &pmc_lock_class); + + irq_set_chip_and_handler(virq, &pmc_irq, + handle_level_irq); + set_irq_flags(virq, IRQF_VALID); + irq_set_chip_data(virq, pmc); + + return 0; +} + +static int pmc_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_pmc *pmc = d->host_data; + const struct at91_pmc_caps *caps = pmc->caps; + + if (WARN_ON(intsize < 1)) + return -EINVAL; + + *out_hwirq = intspec[0]; + + if (!(caps->available_irqs & (1 << *out_hwirq))) + return -EINVAL; + + *out_type = IRQ_TYPE_LEVEL_HIGH; + + return 0; +} + +static struct irq_domain_ops pmc_irq_ops = { + .map = pmc_irq_map, + .xlate = pmc_irq_domain_xlate, +}; + +static irqreturn_t pmc_irq_handler(int irq, void *data) +{ + struct at91_pmc *pmc = (struct at91_pmc *)data; + unsigned long sr; + int n; + + sr = pmc_read(pmc, AT91_PMC_SR) & pmc_read(pmc, AT91_PMC_IMR); + if (!sr) + return IRQ_NONE; + + for_each_set_bit(n, &sr, BITS_PER_LONG) + generic_handle_irq(irq_find_mapping(pmc->irqdomain, n)); + + return IRQ_HANDLED; +} + +static const struct at91_pmc_caps at91rm9200_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | + AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | + AT91_PMC_PCK3RDY, +}; + +static const struct at91_pmc_caps at91sam9260_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | + AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY, +}; + +static const struct at91_pmc_caps at91sam9g45_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | + AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY, +}; + +static const struct at91_pmc_caps at91sam9n12_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB | + AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS | + AT91_PMC_MOSCRCS | AT91_PMC_CFDEV, +}; + +static const struct at91_pmc_caps at91sam9x5_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | + AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS | + AT91_PMC_MOSCRCS | AT91_PMC_CFDEV, +}; + +static const struct at91_pmc_caps sama5d3_caps = { + .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY | + AT91_PMC_LOCKU | AT91_PMC_PCK0RDY | + AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY | + AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS | + AT91_PMC_CFDEV, +}; + +static struct at91_pmc *__init at91_pmc_init(struct device_node *np, + void __iomem *regbase, int virq, + const struct at91_pmc_caps *caps) +{ + struct at91_pmc *pmc; + + if (!regbase || !virq || !caps) + return NULL; + + at91_pmc_base = regbase; + + pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); + if (!pmc) + return NULL; + + spin_lock_init(&pmc->lock); + pmc->regbase = regbase; + pmc->virq = virq; + pmc->caps = caps; + + pmc->irqdomain = irq_domain_add_linear(np, 32, &pmc_irq_ops, pmc); + + if (!pmc->irqdomain) + goto out_free_pmc; + + pmc_write(pmc, AT91_PMC_IDR, 0xffffffff); + if (request_irq(pmc->virq, pmc_irq_handler, IRQF_SHARED, "pmc", pmc)) + goto out_remove_irqdomain; + + return pmc; + +out_remove_irqdomain: + irq_domain_remove(pmc->irqdomain); +out_free_pmc: + kfree(pmc); + + return NULL; +} + +static const struct of_device_id pmc_clk_ids[] __initdata = { + /* Main clock */ + { + .compatible = "atmel,at91rm9200-clk-main", + .data = of_at91rm9200_clk_main_setup, + }, + /* PLL clocks */ + { + .compatible = "atmel,at91rm9200-clk-pll", + .data = of_at91rm9200_clk_pll_setup, + }, + { + .compatible = "atmel,at91sam9g45-clk-pll", + .data = of_at91sam9g45_clk_pll_setup, + }, + { + .compatible = "atmel,at91sam9g20-clk-pllb", + .data = of_at91sam9g20_clk_pllb_setup, + }, + { + .compatible = "atmel,sama5d3-clk-pll", + .data = of_sama5d3_clk_pll_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-plldiv", + .data = of_at91sam9x5_clk_plldiv_setup, + }, + /* Master clock */ + { + .compatible = "atmel,at91rm9200-clk-master", + .data = of_at91rm9200_clk_master_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-master", + .data = of_at91sam9x5_clk_master_setup, + }, + /* System clocks */ + { + .compatible = "atmel,at91rm9200-clk-system", + .data = of_at91rm9200_clk_sys_setup, + }, + /* Peripheral clocks */ + { + .compatible = "atmel,at91rm9200-clk-peripheral", + .data = of_at91rm9200_clk_periph_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-peripheral", + .data = of_at91sam9x5_clk_periph_setup, + }, + /* Programmable clocks */ +#if defined(CONFIG_AT91_PROGRAMMABLE_CLOCKS) + { + .compatible = "atmel,at91rm9200-clk-programmable", + .data = of_at91rm9200_clk_prog_setup, + }, + { + .compatible = "atmel,at91sam9g45-clk-programmable", + .data = of_at91sam9g45_clk_prog_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-programmable", + .data = of_at91sam9x5_clk_prog_setup, + }, +#endif + /* UTMI clock */ +#if defined(CONFIG_HAVE_AT91_UTMI) + { + .compatible = "atmel,at91sam9x5-clk-utmi", + .data = of_at91sam9x5_clk_utmi_setup, + }, +#endif + /* USB clock */ +#if defined(CONFIG_HAVE_AT91_USB_CLK) + { + .compatible = "atmel,at91rm9200-clk-usb", + .data = of_at91rm9200_clk_usb_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-usb", + .data = of_at91sam9x5_clk_usb_setup, + }, + { + .compatible = "atmel,at91sam9n12-clk-usb", + .data = of_at91sam9n12_clk_usb_setup, + }, +#endif + /* SMD clock */ +#if defined(CONFIG_HAVE_AT91_SMD) + { + .compatible = "atmel,at91sam9x5-clk-smd", + .data = of_at91sam9x5_clk_smd_setup, + }, +#endif + { /*sentinel*/ } +}; + +static void __init of_at91_pmc_setup(struct device_node *np, + const struct at91_pmc_caps *caps) +{ + struct at91_pmc *pmc; + struct device_node *childnp; + void (*clk_setup)(struct device_node *, struct at91_pmc *); + const struct of_device_id *clk_id; + void __iomem *regbase = of_iomap(np, 0); + int virq; + + if (!regbase) + return; + + virq = irq_of_parse_and_map(np, 0); + if (!virq) + return; + + pmc = at91_pmc_init(np, regbase, virq, caps); + if (!pmc) + return; + for_each_child_of_node(np, childnp) { + clk_id = of_match_node(pmc_clk_ids, childnp); + if (!clk_id) + continue; + clk_setup = clk_id->data; + clk_setup(childnp, pmc); + } +} + +static void __init of_at91rm9200_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91rm9200_caps); +} +CLK_OF_DECLARE(at91rm9200_clk_pmc, "atmel,at91rm9200-pmc", + of_at91rm9200_pmc_setup); + +static void __init of_at91sam9260_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91sam9260_caps); +} +CLK_OF_DECLARE(at91sam9260_clk_pmc, "atmel,at91sam9260-pmc", + of_at91sam9260_pmc_setup); + +static void __init of_at91sam9g45_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91sam9g45_caps); +} +CLK_OF_DECLARE(at91sam9g45_clk_pmc, "atmel,at91sam9g45-pmc", + of_at91sam9g45_pmc_setup); + +static void __init of_at91sam9n12_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91sam9n12_caps); +} +CLK_OF_DECLARE(at91sam9n12_clk_pmc, "atmel,at91sam9n12-pmc", + of_at91sam9n12_pmc_setup); + +static void __init of_at91sam9x5_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &at91sam9x5_caps); +} +CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc", + of_at91sam9x5_pmc_setup); + +static void __init of_sama5d3_pmc_setup(struct device_node *np) +{ + of_at91_pmc_setup(np, &sama5d3_caps); +} +CLK_OF_DECLARE(sama5d3_clk_pmc, "atmel,sama5d3-pmc", + of_sama5d3_pmc_setup); diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h new file mode 100644 index 000000000000..ba8d14233f80 --- /dev/null +++ b/drivers/clk/at91/pmc.h @@ -0,0 +1,116 @@ +/* + * drivers/clk/at91/pmc.h + * + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __PMC_H_ +#define __PMC_H_ + +#include <linux/io.h> +#include <linux/irqdomain.h> +#include <linux/spinlock.h> + +struct clk_range { + unsigned long min; + unsigned long max; +}; + +#define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,} + +struct at91_pmc_caps { + u32 available_irqs; +}; + +struct at91_pmc { + void __iomem *regbase; + int virq; + spinlock_t lock; + const struct at91_pmc_caps *caps; + struct irq_domain *irqdomain; +}; + +static inline void pmc_lock(struct at91_pmc *pmc) +{ + spin_lock(&pmc->lock); +} + +static inline void pmc_unlock(struct at91_pmc *pmc) +{ + spin_unlock(&pmc->lock); +} + +static inline u32 pmc_read(struct at91_pmc *pmc, int offset) +{ + return readl(pmc->regbase + offset); +} + +static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value) +{ + writel(value, pmc->regbase + offset); +} + +int of_at91_get_clk_range(struct device_node *np, const char *propname, + struct clk_range *range); + +extern void __init of_at91rm9200_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc); + +extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9g45_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_sama5d3_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np, + struct at91_pmc *pmc); + +extern void __init of_at91rm9200_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc); + +extern void __init of_at91rm9200_clk_sys_setup(struct device_node *np, + struct at91_pmc *pmc); + +extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc); + +#if defined(CONFIG_AT91_PROGRAMMABLE_CLOCKS) +extern void __init of_at91rm9200_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); +#endif + +#if defined(CONFIG_HAVE_AT91_UTMI) +extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, + struct at91_pmc *pmc); +#endif + +#if defined(CONFIG_HAVE_AT91_USB_CLK) +extern void __init of_at91rm9200_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); +#endif + +#if defined(CONFIG_HAVE_AT91_SMD) +extern void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, + struct at91_pmc *pmc); +#endif + +#endif /* __PMC_H_ */ diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 0b10a9030f4e..98b6b6ef7e5c 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -22,6 +22,7 @@ #include <linux/delay.h> #include <linux/spinlock.h> #include <linux/timer.h> +#include <linux/of.h> #include <linux/omap-dma.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> @@ -90,17 +91,6 @@ #define OMAP_MMC_CMDTYPE_AC 2 #define OMAP_MMC_CMDTYPE_ADTC 3 -#define OMAP_DMA_MMC_TX 21 -#define OMAP_DMA_MMC_RX 22 -#define OMAP_DMA_MMC2_TX 54 -#define OMAP_DMA_MMC2_RX 55 - -#define OMAP24XX_DMA_MMC2_TX 47 -#define OMAP24XX_DMA_MMC2_RX 48 -#define OMAP24XX_DMA_MMC1_TX 61 -#define OMAP24XX_DMA_MMC1_RX 62 - - #define DRIVER_NAME "mmci-omap" /* Specifies how often in millisecs to poll for card status changes @@ -1330,7 +1320,7 @@ static int mmc_omap_probe(struct platform_device *pdev) struct mmc_omap_host *host = NULL; struct resource *res; dma_cap_mask_t mask; - unsigned sig; + unsigned sig = 0; int i, ret = 0; int irq; @@ -1340,7 +1330,7 @@ static int mmc_omap_probe(struct platform_device *pdev) } if (pdata->nr_slots == 0) { dev_err(&pdev->dev, "no slots\n"); - return -ENXIO; + return -EPROBE_DEFER; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1407,19 +1397,20 @@ static int mmc_omap_probe(struct platform_device *pdev) host->dma_tx_burst = -1; host->dma_rx_burst = -1; - if (mmc_omap2()) - sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX; - else - sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX; - host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); + if (res) + sig = res->start; + host->dma_tx = dma_request_slave_channel_compat(mask, + omap_dma_filter_fn, &sig, &pdev->dev, "tx"); if (!host->dma_tx) dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n", sig); - if (mmc_omap2()) - sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX; - else - sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX; - host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); + if (res) + sig = res->start; + host->dma_rx = dma_request_slave_channel_compat(mask, + omap_dma_filter_fn, &sig, &pdev->dev, "rx"); if (!host->dma_rx) dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n", sig); @@ -1512,12 +1503,20 @@ static int mmc_omap_remove(struct platform_device *pdev) return 0; } +#if IS_BUILTIN(CONFIG_OF) +static const struct of_device_id mmc_omap_match[] = { + { .compatible = "ti,omap2420-mmc", }, + { }, +}; +#endif + static struct platform_driver mmc_omap_driver = { .probe = mmc_omap_probe, .remove = mmc_omap_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(mmc_omap_match), }, }; diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 2cb52e0438df..9f71d9fdcc14 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -326,7 +326,7 @@ static int vbus_is_present(struct usba_udc *udc) #if defined(CONFIG_ARCH_AT91SAM9RL) -#include <mach/at91_pmc.h> +#include <linux/clk/at91_pmc.h> static void toggle_bias(int is_on) { diff --git a/include/dt-bindings/clk/at91.h b/include/dt-bindings/clk/at91.h new file mode 100644 index 000000000000..0b4cb999a3f7 --- /dev/null +++ b/include/dt-bindings/clk/at91.h @@ -0,0 +1,22 @@ +/* + * This header provides constants for AT91 pmc status. + * + * The constants defined in this header are being used in dts. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _DT_BINDINGS_CLK_AT91_H +#define _DT_BINDINGS_CLK_AT91_H + +#define AT91_PMC_MOSCS 0 /* MOSCS Flag */ +#define AT91_PMC_LOCKA 1 /* PLLA Lock */ +#define AT91_PMC_LOCKB 2 /* PLLB Lock */ +#define AT91_PMC_MCKRDY 3 /* Master Clock */ +#define AT91_PMC_LOCKU 6 /* UPLL Lock */ +#define AT91_PMC_PCKRDY(id) (8 + (id)) /* Programmable Clock */ +#define AT91_PMC_MOSCSELS 16 /* Main Oscillator Selection */ +#define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */ +#define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */ + +#endif diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/include/linux/clk/at91_pmc.h index c604cc69acb5..a6911ebbd02a 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ b/include/linux/clk/at91_pmc.h @@ -1,5 +1,5 @@ /* - * arch/arm/mach-at91/include/mach/at91_pmc.h + * include/linux/clk/at91_pmc.h * * Copyright (C) 2005 Ivan Kokshaysky * Copyright (C) SAN People @@ -164,6 +164,8 @@ extern void __iomem *at91_pmc_base; #define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */ #define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */ +#define AT91_PMC_PLLICPR 0x80 /* PLL Charge Pump Current Register */ + #define AT91_PMC_PROT 0xe4 /* Write Protect Mode Register [some SAM9] */ #define AT91_PMC_WPEN (0x1 << 0) /* Write Protect Enable */ #define AT91_PMC_WPKEY (0xffffff << 8) /* Write Protect Key */ |