Commit e29402ed authored by Olof Johansson's avatar Olof Johansson

Merge branch 'mxs/dt/for-3.5' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/dt2

* 'mxs/dt/for-3.5' of git://git.linaro.org/people/shawnguo/linux-2.6: (51 commits)
  ARM: dts: enable audio support for imx28-evk
  ARM: dts: enable i2c device for imx28-evk
  i2c: mxs: add device tree probe support
  ARM: dts: enable mmc for imx28-evk
  ARM: dts: enable mmc for imx23-evk
  mmc: mxs-mmc: add device tree support
  mmc: mxs-mmc: copy wp_gpio in struct mxs_mmc_host
  mmc: mxs-mmc: have dma_channel than dma_res in mxs_mmc_host
  mmc: mxs-mmc: use devm_* helper to make cleanup simpler
  mmc: mxs-mmc: move header from mach into linux folder
  mmc: mxs-mmc: get rid of the use of cpu_is_xxx
  mmc: mxs-mmc: let ssp_is_old take host as parameter
  mmc: mxs-mmc: use global stmp_device functionality
  ARM: mxs: add gpio support for device tree boot
  gpio/mxs: add device tree probe
  gpio/mxs: get rid of the use of cpu_is_xxx
  gpio/mxs: use devm_* helpers to make error handling simple
  ARM: mxs: add mxs-dma dt support
  ARM: mxs: do not add dma device by default
  dma: mxs-dma: add device tree probe support
  ...
parents bf98a6ea 530f1d41
Freescale i.MX Platforms Device Tree Bindings
-----------------------------------------------
i.MX23 Evaluation Kit
Required root node properties:
- compatible = "fsl,imx23-evk", "fsl,imx23";
i.MX28 Evaluation Kit
Required root node properties:
- compatible = "fsl,imx28-evk", "fsl,imx28";
i.MX51 Babbage Board
Required root node properties:
- compatible = "fsl,imx51-babbage", "fsl,imx51";
......
* Freescale MXS DMA
Required properties:
- compatible : Should be "fsl,<chip>-dma-apbh" or "fsl,<chip>-dma-apbx"
- reg : Should contain registers location and length
Supported chips:
imx23, imx28.
Examples:
dma-apbh@80004000 {
compatible = "fsl,imx28-dma-apbh";
reg = <0x80004000 2000>;
};
dma-apbx@80024000 {
compatible = "fsl,imx28-dma-apbx";
reg = <0x80024000 2000>;
};
* Freescale MXS GPIO controller
The Freescale MXS GPIO controller is part of MXS PIN controller. The
GPIOs are organized in port/bank. Each port consists of 32 GPIOs.
As the GPIO controller is embedded in the PIN controller and all the
GPIO ports share the same IO space with PIN controller, the GPIO node
will be represented as sub-nodes of MXS pinctrl node.
Required properties for GPIO node:
- compatible : Should be "fsl,<soc>-gpio". The supported SoCs include
imx23 and imx28.
- interrupts : Should be the port interrupt shared by all 32 pins.
- gpio-controller : Marks the device node as a gpio controller.
- #gpio-cells : Should be two. The first cell is the pin number and
the second cell is used to specify optional parameters (currently
unused).
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells : Should be 2. The first cell is the GPIO number.
The second cell bits[3:0] is used to specify trigger type and level flags:
1 = low-to-high edge triggered.
2 = high-to-low edge triggered.
4 = active high level-sensitive.
8 = active low level-sensitive.
Note: Each GPIO port should have an alias correctly numbered in "aliases"
node.
Examples:
aliases {
gpio0 = &gpio0;
gpio1 = &gpio1;
gpio2 = &gpio2;
gpio3 = &gpio3;
gpio4 = &gpio4;
};
pinctrl@80018000 {
compatible = "fsl,imx28-pinctrl", "simple-bus";
reg = <0x80018000 2000>;
gpio0: gpio@0 {
compatible = "fsl,imx28-gpio";
interrupts = <127>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio1: gpio@1 {
compatible = "fsl,imx28-gpio";
interrupts = <126>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio2: gpio@2 {
compatible = "fsl,imx28-gpio";
interrupts = <125>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio3: gpio@3 {
compatible = "fsl,imx28-gpio";
interrupts = <124>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio4: gpio@4 {
compatible = "fsl,imx28-gpio";
interrupts = <123>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
* Freescale MXS Inter IC (I2C) Controller
Required properties:
- compatible: Should be "fsl,<chip>-i2c"
- reg: Should contain registers location and length
- interrupts: Should contain ERROR and DMA interrupts
Examples:
i2c0: i2c@80058000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx28-i2c";
reg = <0x80058000 2000>;
interrupts = <111 68>;
};
* Freescale MXS MMC controller
The Freescale MXS Synchronous Serial Ports (SSP) can act as a MMC controller
to support MMC, SD, and SDIO types of memory cards.
Required properties:
- compatible: Should be "fsl,<chip>-mmc". The supported chips include
imx23 and imx28.
- reg: Should contain registers location and length
- interrupts: Should contain ERROR and DMA interrupts
- fsl,ssp-dma-channel: APBH DMA channel for the SSP
- bus-width: Number of data lines, can be <1>, <4>, or <8>
Optional properties:
- wp-gpios: Specify GPIOs for write protection
Examples:
ssp0: ssp@80010000 {
compatible = "fsl,imx28-mmc";
reg = <0x80010000 2000>;
interrupts = <96 82>;
fsl,ssp-dma-channel = <0>;
bus-width = <8>;
};
......@@ -468,7 +468,10 @@ config ARCH_MXS
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
select CLKSRC_MMIO
select COMMON_CLK
select HAVE_CLK_PREPARE
select PINCTRL
select USE_OF
help
Support for Freescale MXS-based family of processors
......
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/dts-v1/;
/include/ "imx23.dtsi"
/ {
model = "Freescale i.MX23 Evaluation Kit";
compatible = "fsl,imx23-evk", "fsl,imx23";
memory {
reg = <0x40000000 0x08000000>;
};
apb@80000000 {
apbh@80000000 {
ssp0: ssp@80010000 {
compatible = "fsl,imx23-mmc";
pinctrl-names = "default";
pinctrl-0 = <&mmc0_8bit_pins_a &mmc0_pins_fixup>;
bus-width = <8>;
wp-gpios = <&gpio1 30 0>;
status = "okay";
};
};
apbx@80040000 {
duart: serial@80070000 {
pinctrl-names = "default";
pinctrl-0 = <&duart_pins_a>;
status = "okay";
};
};
};
};
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/include/ "skeleton.dtsi"
/ {
interrupt-parent = <&icoll>;
aliases {
gpio0 = &gpio0;
gpio1 = &gpio1;
gpio2 = &gpio2;
};
cpus {
cpu@0 {
compatible = "arm,arm926ejs";
};
};
apb@80000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x80000000 0x80000>;
ranges;
apbh@80000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x80000000 0x40000>;
ranges;
icoll: interrupt-controller@80000000 {
compatible = "fsl,imx23-icoll", "fsl,mxs-icoll";
interrupt-controller;
#interrupt-cells = <1>;
reg = <0x80000000 0x2000>;
};
dma-apbh@80004000 {
compatible = "fsl,imx23-dma-apbh";
reg = <0x80004000 2000>;
};
ecc@80008000 {
reg = <0x80008000 2000>;
status = "disabled";
};
bch@8000a000 {
reg = <0x8000a000 2000>;
status = "disabled";
};
gpmi@8000c000 {
reg = <0x8000c000 2000>;
status = "disabled";
};
ssp0: ssp@80010000 {
reg = <0x80010000 2000>;
interrupts = <15 14>;
fsl,ssp-dma-channel = <1>;
status = "disabled";
};
etm@80014000 {
reg = <0x80014000 2000>;
status = "disabled";
};
pinctrl@80018000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx23-pinctrl", "simple-bus";
reg = <0x80018000 2000>;
gpio0: gpio@0 {
compatible = "fsl,imx23-gpio", "fsl,mxs-gpio";
interrupts = <16>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio1: gpio@1 {
compatible = "fsl,imx23-gpio", "fsl,mxs-gpio";
interrupts = <17>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio2: gpio@2 {
compatible = "fsl,imx23-gpio", "fsl,mxs-gpio";
interrupts = <18>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
duart_pins_a: duart@0 {
reg = <0>;
fsl,pinmux-ids = <0x11a2 0x11b2>;
fsl,drive-strength = <0>;
fsl,voltage = <1>;
fsl,pull-up = <0>;
};
mmc0_8bit_pins_a: mmc0-8bit@0 {
reg = <0>;
fsl,pinmux-ids = <0x2020 0x2030 0x2040
0x2050 0x0082 0x0092 0x00a2
0x00b2 0x2000 0x2010 0x2060>;
fsl,drive-strength = <1>;
fsl,voltage = <1>;
fsl,pull-up = <1>;
};
mmc0_pins_fixup: mmc0-pins-fixup {
fsl,pinmux-ids = <0x2010 0x2060>;
fsl,pull-up = <0>;
};
};
digctl@8001c000 {
reg = <0x8001c000 2000>;
status = "disabled";
};
emi@80020000 {
reg = <0x80020000 2000>;
status = "disabled";
};
dma-apbx@80024000 {
compatible = "fsl,imx23-dma-apbx";
reg = <0x80024000 2000>;
};
dcp@80028000 {
reg = <0x80028000 2000>;
status = "disabled";
};
pxp@8002a000 {
reg = <0x8002a000 2000>;
status = "disabled";
};
ocotp@8002c000 {
reg = <0x8002c000 2000>;
status = "disabled";
};
axi-ahb@8002e000 {
reg = <0x8002e000 2000>;
status = "disabled";
};
lcdif@80030000 {
reg = <0x80030000 2000>;
status = "disabled";
};
ssp1: ssp@80034000 {
reg = <0x80034000 2000>;
interrupts = <2 20>;
fsl,ssp-dma-channel = <2>;
status = "disabled";
};
tvenc@80038000 {
reg = <0x80038000 2000>;
status = "disabled";
};
};
apbx@80040000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x80040000 0x40000>;
ranges;
clkctl@80040000 {
reg = <0x80040000 2000>;
status = "disabled";
};
saif0: saif@80042000 {
reg = <0x80042000 2000>;
status = "disabled";
};
power@80044000 {
reg = <0x80044000 2000>;
status = "disabled";
};
saif1: saif@80046000 {
reg = <0x80046000 2000>;
status = "disabled";
};
audio-out@80048000 {
reg = <0x80048000 2000>;
status = "disabled";
};
audio-in@8004c000 {
reg = <0x8004c000 2000>;
status = "disabled";
};
lradc@80050000 {
reg = <0x80050000 2000>;
status = "disabled";
};
spdif@80054000 {
reg = <0x80054000 2000>;
status = "disabled";
};
i2c@80058000 {
reg = <0x80058000 2000>;
status = "disabled";
};
rtc@8005c000 {
reg = <0x8005c000 2000>;
status = "disabled";
};
pwm@80064000 {
reg = <0x80064000 2000>;
status = "disabled";
};
timrot@80068000 {
reg = <0x80068000 2000>;
status = "disabled";
};
auart0: serial@8006c000 {
reg = <0x8006c000 0x2000>;
status = "disabled";
};
auart1: serial@8006e000 {
reg = <0x8006e000 0x2000>;
status = "disabled";
};
duart: serial@80070000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x80070000 0x2000>;
interrupts = <0>;
status = "disabled";
};
usbphy@8007c000 {
reg = <0x8007c000 0x2000>;
status = "disabled";
};
};
};
ahb@80080000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x80080000 0x80000>;
ranges;
usbctrl@80080000 {
reg = <0x80080000 0x10000>;
status = "disabled";
};
};
};
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/dts-v1/;
/include/ "imx28.dtsi"
/ {
model = "Freescale i.MX28 Evaluation Kit";
compatible = "fsl,imx28-evk", "fsl,imx28";
memory {
reg = <0x40000000 0x08000000>;
};
apb@80000000 {
apbh@80000000 {
ssp0: ssp@80010000 {
compatible = "fsl,imx28-mmc";
pinctrl-names = "default";
pinctrl-0 = <&mmc0_8bit_pins_a
&mmc0_cd_cfg &mmc0_sck_cfg>;
bus-width = <8>;
wp-gpios = <&gpio2 12 0>;
status = "okay";
};
ssp1: ssp@80012000 {
compatible = "fsl,imx28-mmc";
bus-width = <8>;
wp-gpios = <&gpio0 28 0>;
status = "okay";
};
};
apbx@80040000 {
saif0: saif@80042000 {
pinctrl-names = "default";
pinctrl-0 = <&saif0_pins_a>;
status = "okay";
};
saif1: saif@80046000 {
pinctrl-names = "default";
pinctrl-0 = <&saif1_pins_a>;
fsl,saif-master = <&saif0>;
status = "okay";
};
i2c0: i2c@80058000 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
sgtl5000: codec@0a {
compatible = "fsl,sgtl5000";
reg = <0x0a>;
VDDA-supply = <&reg_3p3v>;
VDDIO-supply = <&reg_3p3v>;
};
};
duart: serial@80074000 {
pinctrl-names = "default";
pinctrl-0 = <&duart_pins_a>;
status = "okay";
};
};
};
ahb@80080000 {
mac0: ethernet@800f0000 {
phy-mode = "rmii";
pinctrl-names = "default";
pinctrl-0 = <&mac0_pins_a>;
status = "okay";
};
mac1: ethernet@800f4000 {
phy-mode = "rmii";
pinctrl-names = "default";
pinctrl-0 = <&mac1_pins_a>;
status = "okay";
};
};
regulators {
compatible = "simple-bus";
reg_3p3v: 3p3v {
compatible = "regulator-fixed";
regulator-name = "3P3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
sound {
compatible = "fsl,imx28-evk-sgtl5000",
"fsl,mxs-audio-sgtl5000";
model = "imx28-evk-sgtl5000";
saif-controllers = <&saif0 &saif1>;
audio-codec = <&sgtl5000>;
};
};
This diff is collapsed.
......@@ -22,6 +22,7 @@ CONFIG_BLK_DEV_INTEGRITY=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_MXS=y
CONFIG_MACH_MXS_DT=y
CONFIG_MACH_MX23EVK=y
CONFIG_MACH_MX28EVK=y
CONFIG_MACH_STMP378X_DEVB=y
......
......@@ -842,6 +842,8 @@ config SOC_IMX6Q
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
select HAVE_SMP
select PINCTRL
select PINCTRL_IMX6Q
select USE_OF
help
......
......@@ -14,6 +14,7 @@
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/machine.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <mach/common.h>
......@@ -81,6 +82,8 @@ static void __init imx51_dt_init(void)
of_irq_init(imx51_irq_match);
pinctrl_provide_dummies();
node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
if (node) {
of_id = of_match_node(imx51_iomuxc_of_match, node);
......
......@@ -15,6 +15,7 @@
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/machine.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <mach/common.h>
......@@ -88,6 +89,8 @@ static void __init imx53_dt_init(void)
of_irq_init(imx53_irq_match);
pinctrl_provide_dummies();
node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
if (node) {
of_id = of_match_node(imx53_iomuxc_of_match, node);
......
......@@ -19,6 +19,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/machine.h>
#include <linux/phy.h>
#include <linux/micrel_phy.h>
#include <asm/smp_twd.h>
......@@ -77,6 +78,12 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev)
static void __init imx6q_init_machine(void)
{
/*
* This should be removed when all imx6q boards have pinctrl
* states for devices defined in device tree.
*/
pinctrl_provide_dummies();
if (of_machine_is_compatible("fsl,imx6q-sabrelite"))
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
ksz9021rn_phy_fixup);
......
......@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/pinctrl/machine.h>
#include <asm/mach/map.h>
......@@ -58,4 +59,5 @@ void __init imx1_soc_init(void)
MX1_GPIO_INT_PORTC, 0);
mxc_register_gpio("imx1-gpio", 3, MX1_GPIO4_BASE_ADDR, SZ_256,
MX1_GPIO_INT_PORTD, 0);
pinctrl_provide_dummies();
}
......@@ -20,6 +20,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/pinctrl/machine.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/devices-common.h>
......@@ -88,6 +89,7 @@ void __init imx21_soc_init(void)
mxc_register_gpio("imx21-gpio", 4, MX21_GPIO5_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
pinctrl_provide_dummies();
imx_add_imx_dma();
platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
ARRAY_SIZE(imx21_audmux_res));
......
......@@ -19,6 +19,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/pinctrl/machine.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
......@@ -95,6 +96,7 @@ void __init imx25_soc_init(void)
mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
pinctrl_provide_dummies();
/* i.mx25 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
/* i.mx25 has the i.mx31 type audmux */
......
......@@ -20,6 +20,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/pinctrl/machine.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/devices-common.h>
......@@ -89,6 +90,7 @@ void __init imx27_soc_init(void)
mxc_register_gpio("imx21-gpio", 4, MX27_GPIO5_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
pinctrl_provide_dummies();
imx_add_imx_dma();
/* imx27 has the imx21 type audmux */
platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
......
......@@ -19,6 +19,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/pinctrl/machine.h>
#include <asm/pgtable.h>
#include <asm/system_misc.h>
......@@ -267,6 +268,7 @@ void __init imx35_soc_init(void)
mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
pinctrl_provide_dummies();
if (to_version == 1) {
strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
strlen(imx35_sdma_pdata.fw_name));
......
......@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/pinctrl/machine.h>
#include <asm/system_misc.h>
#include <asm/mach/map.h>
......@@ -223,6 +224,7 @@ void __init imx53_soc_init(void)
mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
pinctrl_provide_dummies();
/* i.mx53 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
......
......@@ -7,16 +7,28 @@ config MXS_OCOTP
config SOC_IMX23
bool
select ARM_AMBA
select CPU_ARM926T
select HAVE_PWM
select PINCTRL_IMX23
config SOC_IMX28
bool
select ARM_AMBA
select CPU_ARM926T
select HAVE_PWM
select PINCTRL_IMX28
comment "MXS platforms:"
config MACH_MXS_DT
bool "Support MXS platforms from device tree"
select SOC_IMX23
select SOC_IMX28
help
Include support for Freescale MXS platforms(i.MX23 and i.MX28)
using the device tree for discovery
config MACH_STMP378X_DEVB
bool "Support STMP378x_devb Platform"
select SOC_IMX23
......
# Common support
obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o mm.o
obj-y := devices.o icoll.o iomux.o system.o timer.o mm.o
obj-$(CONFIG_MXS_OCOTP) += ocotp.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_SOC_IMX23) += clock-mx23.o
obj-$(CONFIG_SOC_IMX28) += clock-mx28.o
obj-$(CONFIG_MACH_MXS_DT) += mach-mxs.o
obj-$(CONFIG_MACH_STMP378X_DEVB) += mach-stmp378x_devb.o
obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
......
This diff is collapsed.
This diff is collapsed.
/*
* Based on arch/arm/plat-omap/clock.c
*
* Copyright (C) 2004 - 2005 Nokia corporation
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
* Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
* Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
/* #define DEBUG */
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/semaphore.h>
#include <linux/string.h>
#include <mach/clock.h>
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
/*-------------------------------------------------------------------------
* Standard clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
static void __clk_disable(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return;
WARN_ON(!clk->usecount);
if (!(--clk->usecount)) {
if (clk->disable)
clk->disable(clk);
__clk_disable(clk->parent);
}
}
static int __clk_enable(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
if (clk->usecount++ == 0) {
__clk_enable(clk->parent);
if (clk->enable)
clk->enable(clk);
}
return 0;
}
/*
* The clk_enable/clk_disable could be called by drivers in atomic context,
* so they should not really hold mutex. Instead, clk_prepare/clk_unprepare
* can hold a mutex, as the pair will only be called in non-atomic context.
* Before migrating to common clk framework, we can have __clk_enable and
* __clk_disable called in clk_prepare/clk_unprepare with mutex held and
* leave clk_enable/clk_disable as the dummy functions.
*/
int clk_prepare(struct clk *clk)
{
int ret = 0;
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
mutex_lock(&clocks_mutex);
ret = __clk_enable(clk);
mutex_unlock(&clocks_mutex);
return ret;
}
EXPORT_SYMBOL(clk_prepare);
void clk_unprepare(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return;
mutex_lock(&clocks_mutex);
__clk_disable(clk);
mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unprepare);
int clk_enable(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
/* nothing to do */
}
EXPORT_SYMBOL(clk_disable);
/* Retrieve the *current* clock rate. If the clock itself
* does not provide a special calculation routine, ask
* its parent and so on, until one is able to return
* a valid clock rate
*/
unsigned long clk_get_rate(struct clk *clk)
{
if (clk == NULL || IS_ERR(clk))
return 0UL;
if (clk->get_rate)
return clk->get_rate(clk);
return clk_get_rate(clk->parent);
}
EXPORT_SYMBOL(clk_get_rate);
/* Round the requested clock rate to the nearest supported
* rate that is less than or equal to the requested rate.
* This is dependent on the clock's current parent.
*/
long clk_round_rate(struct clk *clk, unsigned long rate)
{
if (clk == NULL || IS_ERR(clk) || !clk->round_rate)
return 0;
return clk->round_rate(clk, rate);
}
EXPORT_SYMBOL(clk_round_rate);
/* Set the clock to the requested clock rate. The rate must
* match a supported rate exactly based on what clk_round_rate returns
*/
int clk_set_rate(struct clk *clk, unsigned long rate)
{
int ret = -EINVAL;
if (clk == NULL || IS_ERR(clk) || clk->set_rate == NULL || rate == 0)
return ret;
mutex_lock(&clocks_mutex);
ret = clk->set_rate(clk, rate);
mutex_unlock(&clocks_mutex);
return ret;
}
EXPORT_SYMBOL(clk_set_rate);
/* Set the clock's parent to another clock source */
int clk_set_parent(struct clk *clk, struct clk *parent)
{
int ret = -EINVAL;
struct clk *old;
if (clk == NULL || IS_ERR(clk) || parent == NULL ||
IS_ERR(parent) || clk->set_parent == NULL)
return ret;
if (clk->usecount)
clk_prepare_enable(parent);
mutex_lock(&clocks_mutex);
ret = clk->set_parent(clk, parent);
if (ret == 0) {
old = clk->parent;
clk->parent = parent;
} else {
old = parent;
}
mutex_unlock(&clocks_mutex);
if (clk->usecount)
clk_disable(old);
return ret;
}
EXPORT_SYMBOL(clk_set_parent);
/* Retrieve the clock's parent clock source */
struct clk *clk_get_parent(struct clk *clk)
{
struct clk *ret = NULL;
if (clk == NULL || IS_ERR(clk))
return ret;
return clk->parent;
}
EXPORT_SYMBOL(clk_get_parent);
config MXS_HAVE_AMBA_DUART
bool
select ARM_AMBA
config MXS_HAVE_PLATFORM_AUART
bool
......
......@@ -14,7 +14,7 @@
#include <mach/mx28.h>
#include <mach/devices-common.h>
static struct platform_device *__init mxs_add_dma(const char *devid,
struct platform_device *__init mxs_add_dma(const char *devid,
resource_size_t base)
{
struct resource res[] = {
......@@ -29,22 +29,3 @@ static struct platform_device *__init mxs_add_dma(const char *devid,
res, ARRAY_SIZE(res), NULL, 0,
DMA_BIT_MASK(32));
}
static int __init mxs_add_mxs_dma(void)
{
char *apbh = "mxs-dma-apbh";
char *apbx = "mxs-dma-apbx";
if (cpu_is_mx23()) {
mxs_add_dma(apbh, MX23_APBH_DMA_BASE_ADDR);
mxs_add_dma(apbx, MX23_APBX_DMA_BASE_ADDR);
}
if (cpu_is_mx28()) {
mxs_add_dma(apbh, MX28_APBH_DMA_BASE_ADDR);
mxs_add_dma(apbx, MX28_APBX_DMA_BASE_ADDR);
}
return 0;
}
arch_initcall(mxs_add_mxs_dma);
......@@ -14,7 +14,7 @@
#include <mach/devices-common.h>
struct platform_device *__init mxs_add_gpio(
int id, resource_size_t iobase, int irq)
char *name, int id, resource_size_t iobase, int irq)
{
struct resource res[] = {
{
......@@ -29,25 +29,5 @@ struct platform_device *__init mxs_add_gpio(
};
return platform_device_register_resndata(&mxs_apbh_bus,
"gpio-mxs", id, res, ARRAY_SIZE(res), NULL, 0);
name, id, res, ARRAY_SIZE(res), NULL, 0);
}
static int __init mxs_add_mxs_gpio(void)
{
if (cpu_is_mx23()) {
mxs_add_gpio(0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0);
mxs_add_gpio(1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1);
mxs_add_gpio(2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2);
}
if (cpu_is_mx28()) {
mxs_add_gpio(0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0);
mxs_add_gpio(1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1);
mxs_add_gpio(2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2);
mxs_add_gpio(3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3);
mxs_add_gpio(4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4);
}
return 0;
}
postcore_initcall(mxs_add_mxs_gpio);
......@@ -17,8 +17,9 @@
#include <mach/mx28.h>
#include <mach/devices-common.h>
#define mxs_mxs_mmc_data_entry_single(soc, _id, hwid) \
#define mxs_mxs_mmc_data_entry_single(soc, _devid, _id, hwid) \
{ \
.devid = _devid, \
.id = _id, \
.iobase = soc ## _SSP ## hwid ## _BASE_ADDR, \
.dma = soc ## _DMA_SSP ## hwid, \
......@@ -26,23 +27,23 @@
.irq_dma = soc ## _INT_SSP ## hwid ## _DMA, \
}
#define mxs_mxs_mmc_data_entry(soc, _id, hwid) \
[_id] = mxs_mxs_mmc_data_entry_single(soc, _id, hwid)
#define mxs_mxs_mmc_data_entry(soc, _devid, _id, hwid) \
[_id] = mxs_mxs_mmc_data_entry_single(soc, _devid, _id, hwid)
#ifdef CONFIG_SOC_IMX23
const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst = {
mxs_mxs_mmc_data_entry(MX23, 0, 1),
mxs_mxs_mmc_data_entry(MX23, 1, 2),
mxs_mxs_mmc_data_entry(MX23, "imx23-mmc", 0, 1),
mxs_mxs_mmc_data_entry(MX23, "imx23-mmc", 1, 2),
};
#endif
#ifdef CONFIG_SOC_IMX28
const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = {
mxs_mxs_mmc_data_entry(MX28, 0, 0),
mxs_mxs_mmc_data_entry(MX28, 1, 1),
mxs_mxs_mmc_data_entry(MX28, 2, 2),
mxs_mxs_mmc_data_entry(MX28, 3, 3),
mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 0, 0),
mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 1, 1),
mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 2, 2),
mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 3, 3),
};
#endif
......@@ -70,6 +71,6 @@ struct platform_device *__init mxs_add_mxs_mmc(
},
};
return mxs_add_platform_device("mxs-mmc", data->id,
return mxs_add_platform_device(data->devid, data->id,
res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
}
/*
* Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef __MACH_MXS_CLOCK_H__
#define __MACH_MXS_CLOCK_H__
#ifndef __ASSEMBLY__
#include <linux/list.h>
struct module;
struct clk {
int id;
/* Source clock this clk depends on */
struct clk *parent;
/* Reference count of clock enable/disable */
__s8 usecount;
/* Register bit position for clock's enable/disable control. */
u8 enable_shift;
/* Register address for clock's enable/disable control. */
void __iomem *enable_reg;
u32 flags;
/* get the current clock rate (always a fresh value) */
unsigned long (*get_rate) (struct clk *);
/* Function ptr to set the clock to a new rate. The rate must match a
supported rate returned from round_rate. Leave blank if clock is not
programmable */
int (*set_rate) (struct clk *, unsigned long);
/* Function ptr to round the requested clock rate to the nearest
supported rate that is less than or equal to the requested rate. */
unsigned long (*round_rate) (struct clk *, unsigned long);
/* Function ptr to enable the clock. Leave blank if clock can not
be gated. */
int (*enable) (struct clk *);
/* Function ptr to disable the clock. Leave blank if clock can not
be gated. */
void (*disable) (struct clk *);
/* Function ptr to set the parent clock of the clock. */
int (*set_parent) (struct clk *, struct clk *);
};
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
#endif /* __ASSEMBLY__ */
#endif /* __MACH_MXS_CLOCK_H__ */
......@@ -11,26 +11,27 @@
#ifndef __MACH_MXS_COMMON_H__
#define __MACH_MXS_COMMON_H__
struct clk;
extern const u32 *mxs_get_ocotp(void);
extern int mxs_reset_block(void __iomem *);
extern void mxs_timer_init(struct clk *, int);
extern void mxs_timer_init(int);
extern void mxs_restart(char, const char *);
extern int mxs_saif_clkmux_select(unsigned int clkmux);
extern int mx23_register_gpios(void);
extern void mx23_soc_init(void);
extern int mx23_clocks_init(void);
extern void mx23_map_io(void);
extern void mx23_init_irq(void);
extern int mx28_register_gpios(void);
extern void mx28_soc_init(void);
extern int mx28_clocks_init(void);
extern void mx28_map_io(void);
extern void mx28_init_irq(void);
extern void icoll_init_irq(void);
extern int mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask);
extern struct platform_device *mxs_add_dma(const char *devid,
resource_size_t base);
extern struct platform_device *mxs_add_gpio(char *name, int id,
resource_size_t iobase, int irq);
#endif /* __MACH_MXS_COMMON_H__ */
......@@ -87,8 +87,9 @@ struct platform_device * __init mxs_add_mxs_i2c(
const struct mxs_mxs_i2c_data *data);
/* mmc */
#include <mach/mmc.h>
#include <linux/mmc/mxs-mmc.h>
struct mxs_mxs_mmc_data {
const char *devid;
int id;
resource_size_t iobase;
resource_size_t dma;
......
......@@ -207,6 +207,8 @@ static int apx4devkit_phy_fixup(struct phy_device *phy)
static void __init apx4devkit_init(void)
{
mx28_soc_init();
mxs_iomux_setup_multiple_pads(apx4devkit_pads,
ARRAY_SIZE(apx4devkit_pads));
......
......@@ -319,6 +319,8 @@ static struct mxs_mmc_platform_data m28evk_mmc_pdata[] __initdata = {
static void __init m28evk_init(void)
{
mx28_soc_init();
mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads));
mx28_add_duart();
......
......@@ -141,6 +141,8 @@ static void __init mx23evk_init(void)
{
int ret;
mx23_soc_init();
mxs_iomux_setup_multiple_pads(mx23evk_pads, ARRAY_SIZE(mx23evk_pads));
mx23_add_duart();
......
......@@ -226,7 +226,7 @@ static void __init mx28evk_fec_reset(void)
struct clk *clk;
/* Enable fec phy clock */
clk = clk_get_sys("pll2", NULL);
clk = clk_get_sys("enet_out", NULL);
if (!IS_ERR(clk))
clk_prepare_enable(clk);
......@@ -413,6 +413,8 @@ static void __init mx28evk_init(void)
{
int ret;
mx28_soc_init();
mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
mx28_add_duart();
......
/*
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright 2012 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <mach/common.h>
static int __init mxs_icoll_add_irq_domain(struct device_node *np,
struct device_node *interrupt_parent)
{
irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);
return 0;
}
static int __init mxs_gpio_add_irq_domain(struct device_node *np,
struct device_node *interrupt_parent)
{
static int gpio_irq_base = MXS_GPIO_IRQ_START;
irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
gpio_irq_base += 32;
return 0;
}
static const struct of_device_id mxs_irq_match[] __initconst = {
{ .compatible = "fsl,mxs-icoll", .data = mxs_icoll_add_irq_domain, },
{ .compatible = "fsl,mxs-gpio", .data = mxs_gpio_add_irq_domain, },
{ /* sentinel */ }
};
static void __init mxs_dt_init_irq(void)
{
icoll_init_irq();
of_irq_init(mxs_irq_match);
}
static void __init imx23_timer_init(void)
{
mx23_clocks_init();
}
static struct sys_timer imx23_timer = {
.init = imx23_timer_init,
};
static void __init imx28_timer_init(void)
{
mx28_clocks_init();
}
static struct sys_timer imx28_timer = {
.init = imx28_timer_init,
};
static void __init imx28_evk_init(void)
{
struct clk *clk;
/* Enable fec phy clock */
clk = clk_get_sys("enet_out", NULL);
if (!IS_ERR(clk))
clk_prepare_enable(clk);
}
static void __init mxs_machine_init(void)
{
if (of_machine_is_compatible("fsl,imx28-evk"))
imx28_evk_init();
of_platform_populate(NULL, of_default_bus_match_table,
NULL, NULL);
}
static const char *imx23_dt_compat[] __initdata = {
"fsl,imx23-evk",
"fsl,imx23",
NULL,
};
static const char *imx28_dt_compat[] __initdata = {
"fsl,imx28-evk",
"fsl,imx28",
NULL,
};
DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)")
.map_io = mx23_map_io,
.init_irq = mxs_dt_init_irq,
.timer = &imx23_timer,
.init_machine = mxs_machine_init,
.dt_compat = imx23_dt_compat,
.restart = mxs_restart,
MACHINE_END
DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)")
.map_io = mx28_map_io,
.init_irq = mxs_dt_init_irq,
.timer = &imx28_timer,
.init_machine = mxs_machine_init,
.dt_compat = imx28_dt_compat,
.restart = mxs_restart,
MACHINE_END
......@@ -85,6 +85,8 @@ static void __init stmp378x_dvb_init(void)
{
int ret;
mx23_soc_init();
mxs_iomux_setup_multiple_pads(stmp378x_dvb_pads,
ARRAY_SIZE(stmp378x_dvb_pads));
......
......@@ -146,6 +146,8 @@ static struct mxs_mmc_platform_data tx28_mmc0_pdata __initdata = {
static void __init tx28_stk5v3_init(void)
{
mx28_soc_init();
mxs_iomux_setup_multiple_pads(tx28_stk5v3_pads,
ARRAY_SIZE(tx28_stk5v3_pads));
......
......@@ -13,6 +13,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/pinctrl/machine.h>
#include <asm/mach/map.h>
......@@ -61,3 +62,29 @@ void __init mx28_init_irq(void)
{
icoll_init_irq();
}
void __init mx23_soc_init(void)
{
pinctrl_provide_dummies();
mxs_add_dma("imx23-dma-apbh", MX23_APBH_DMA_BASE_ADDR);
mxs_add_dma("imx23-dma-apbx", MX23_APBX_DMA_BASE_ADDR);
mxs_add_gpio("imx23-gpio", 0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0);
mxs_add_gpio("imx23-gpio", 1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1);
mxs_add_gpio("imx23-gpio", 2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2);
}
void __init mx28_soc_init(void)
{
pinctrl_provide_dummies();
mxs_add_dma("imx28-dma-apbh", MX23_APBH_DMA_BASE_ADDR);
mxs_add_dma("imx28-dma-apbx", MX23_APBX_DMA_BASE_ADDR);
mxs_add_gpio("imx28-gpio", 0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0);
mxs_add_gpio("imx28-gpio", 1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1);
mxs_add_gpio("imx28-gpio", 2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2);
mxs_add_gpio("imx28-gpio", 3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3);
mxs_add_gpio("imx28-gpio", 4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4);
}
This diff is collapsed.
This diff is collapsed.
......@@ -37,8 +37,6 @@
#define MXS_MODULE_CLKGATE (1 << 30)
#define MXS_MODULE_SFTRST (1 << 31)
#define CLKCTRL_TIMEOUT 10 /* 10 ms */
static void __iomem *mxs_clkctrl_reset_addr;
/*
......@@ -139,17 +137,3 @@ int mxs_reset_block(void __iomem *reset_addr)
return -ETIMEDOUT;
}
EXPORT_SYMBOL(mxs_reset_block);
int mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask)
{
unsigned long timeout = jiffies + msecs_to_jiffies(CLKCTRL_TIMEOUT);
while (readl_relaxed(MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR)
+ reg_offset) & mask) {
if (time_after(jiffies, timeout)) {
pr_err("Timeout at CLKCTRL + 0x%x\n", reg_offset);
return -ETIMEDOUT;
}
}
return 0;
}
......@@ -20,6 +20,7 @@
* MA 02110-1301, USA.
*/
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/clockchips.h>
......@@ -243,8 +244,16 @@ static int __init mxs_clocksource_init(struct clk *timer_clk)
return 0;
}
void __init mxs_timer_init(struct clk *timer_clk, int irq)
void __init mxs_timer_init(int irq)
{
struct clk *timer_clk;
timer_clk = clk_get_sys("timrot", NULL);
if (IS_ERR(timer_clk)) {
pr_err("%s: failed to get clk\n", __func__);
return;
}
clk_prepare_enable(timer_clk);
/*
......
......@@ -2,3 +2,5 @@
obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \
clk-mux.o clk-divider.o
obj-$(CONFIG_ARCH_MXS) += mxs/
#
# Makefile for mxs specific clk
#
obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o
obj-$(CONFIG_SOC_IMX23) += clk-imx23.o
obj-$(CONFIG_SOC_IMX28) += clk-imx28.o
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/slab.h>
#include "clk.h"
/**
* struct clk_div - mxs integer divider clock
* @divider: the parent class
* @ops: pointer to clk_ops of parent class
* @reg: register address
* @busy: busy bit shift
*
* The mxs divider clock is a subclass of basic clk_divider with an
* addtional busy bit.
*/
struct clk_div {
struct clk_divider divider;
const struct clk_ops *ops;
void __iomem *reg;
u8 busy;
};
static inline struct clk_div *to_clk_div(struct clk_hw *hw)
{
struct clk_divider *divider = container_of(hw, struct clk_divider, hw);
return container_of(divider, struct clk_div, divider);
}
static unsigned long clk_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_div *div = to_clk_div(hw);
return div->ops->recalc_rate(&div->divider.hw, parent_rate);
}
static long clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_div *div = to_clk_div(hw);
return div->ops->round_rate(&div->divider.hw, rate, prate);
}
static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_div *div = to_clk_div(hw);
int ret;
ret = div->ops->set_rate(&div->divider.hw, rate, parent_rate);
if (!ret)
ret = mxs_clk_wait(div->reg, div->busy);
return ret;
}
static struct clk_ops clk_div_ops = {
.recalc_rate = clk_div_recalc_rate,
.round_rate = clk_div_round_rate,
.set_rate = clk_div_set_rate,
};
struct clk *mxs_clk_div(const char *name, const char *parent_name,
void __iomem *reg, u8 shift, u8 width, u8 busy)
{
struct clk_div *div;
struct clk *clk;
struct clk_init_data init;
div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &clk_div_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = (parent_name ? &parent_name: NULL);
init.num_parents = (parent_name ? 1 : 0);
div->reg = reg;
div->busy = busy;
div->divider.reg = reg;
div->divider.shift = shift;
div->divider.width = width;
div->divider.flags = CLK_DIVIDER_ONE_BASED;
div->divider.lock = &mxs_lock;
div->divider.hw.init = &init;
div->ops = &clk_divider_ops;
clk = clk_register(NULL, &div->divider.hw);
if (IS_ERR(clk))
kfree(div);
return clk;
}
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/slab.h>
#include "clk.h"
/**
* struct clk_frac - mxs fractional divider clock
* @hw: clk_hw for the fractional divider clock
* @reg: register address
* @shift: the divider bit shift
* @width: the divider bit width
* @busy: busy bit shift
*
* The clock is an adjustable fractional divider with a busy bit to wait
* when the divider is adjusted.
*/
struct clk_frac {
struct clk_hw hw;
void __iomem *reg;
u8 shift;
u8 width;
u8 busy;
};
#define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw)
static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_frac *frac = to_clk_frac(hw);
u32 div;
div = readl_relaxed(frac->reg) >> frac->shift;
div &= (1 << frac->width) - 1;
return (parent_rate >> frac->width) * div;
}
static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_frac *frac = to_clk_frac(hw);
unsigned long parent_rate = *prate;
u32 div;
u64 tmp;
if (rate > parent_rate)
return -EINVAL;
tmp = rate;
tmp <<= frac->width;
do_div(tmp, parent_rate);
div = tmp;
if (!div)
return -EINVAL;
return (parent_rate >> frac->width) * div;
}
static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_frac *frac = to_clk_frac(hw);
unsigned long flags;
u32 div, val;
u64 tmp;
if (rate > parent_rate)
return -EINVAL;
tmp = rate;
tmp <<= frac->width;
do_div(tmp, parent_rate);
div = tmp;
if (!div)
return -EINVAL;
spin_lock_irqsave(&mxs_lock, flags);
val = readl_relaxed(frac->reg);
val &= ~(((1 << frac->width) - 1) << frac->shift);
val |= div << frac->shift;
writel_relaxed(val, frac->reg);
spin_unlock_irqrestore(&mxs_lock, flags);
return mxs_clk_wait(frac->reg, frac->busy);
}
static struct clk_ops clk_frac_ops = {
.recalc_rate = clk_frac_recalc_rate,
.round_rate = clk_frac_round_rate,
.set_rate = clk_frac_set_rate,
};
struct clk *mxs_clk_frac(const char *name, const char *parent_name,
void __iomem *reg, u8 shift, u8 width, u8 busy)
{
struct clk_frac *frac;
struct clk *clk;
struct clk_init_data init;
frac = kzalloc(sizeof(*frac), GFP_KERNEL);
if (!frac)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &clk_frac_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = (parent_name ? &parent_name: NULL);
init.num_parents = (parent_name ? 1 : 0);
frac->reg = reg;
frac->shift = shift;
frac->width = width;
frac->busy = busy;
frac->hw.init = &init;
clk = clk_register(NULL, &frac->hw);
if (IS_ERR(clk))
kfree(frac);
return clk;
}
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <mach/common.h>
#include <mach/mx23.h>
#include "clk.h"
#define DIGCTRL MX23_IO_ADDRESS(MX23_DIGCTL_BASE_ADDR)
#define CLKCTRL MX23_IO_ADDRESS(MX23_CLKCTRL_BASE_ADDR)
#define PLLCTRL0 (CLKCTRL + 0x0000)
#define CPU (CLKCTRL + 0x0020)
#define HBUS (CLKCTRL + 0x0030)
#define XBUS (CLKCTRL + 0x0040)
#define XTAL (CLKCTRL + 0x0050)
#define PIX (CLKCTRL + 0x0060)
#define SSP (CLKCTRL + 0x0070)
#define GPMI (CLKCTRL + 0x0080)
#define SPDIF (CLKCTRL + 0x0090)
#define EMI (CLKCTRL + 0x00a0)
#define SAIF (CLKCTRL + 0x00c0)
#define TV (CLKCTRL + 0x00d0)
#define ETM (CLKCTRL + 0x00e0)
#define FRAC (CLKCTRL + 0x00f0)
#define CLKSEQ (CLKCTRL + 0x0110)
#define BP_CPU_INTERRUPT_WAIT 12
#define BP_CLKSEQ_BYPASS_SAIF 0
#define BP_CLKSEQ_BYPASS_SSP 5
#define BP_SAIF_DIV_FRAC_EN 16
#define BP_FRAC_IOFRAC 24
static void __init clk_misc_init(void)
{
u32 val;
/* Gate off cpu clock in WFI for power saving */
__mxs_setl(1 << BP_CPU_INTERRUPT_WAIT, CPU);
/* Clear BYPASS for SAIF */
__mxs_clrl(1 << BP_CLKSEQ_BYPASS_SAIF, CLKSEQ);
/* SAIF has to use frac div for functional operation */
val = readl_relaxed(SAIF);
val |= 1 << BP_SAIF_DIV_FRAC_EN;
writel_relaxed(val, SAIF);
/*
* Source ssp clock from ref_io than ref_xtal,
* as ref_xtal only provides 24 MHz as maximum.
*/
__mxs_clrl(1 << BP_CLKSEQ_BYPASS_SSP, CLKSEQ);
/*
* 480 MHz seems too high to be ssp clock source directly,
* so set frac to get a 288 MHz ref_io.
*/
__mxs_clrl(0x3f << BP_FRAC_IOFRAC, FRAC);
__mxs_setl(30 << BP_FRAC_IOFRAC, FRAC);
}
static struct clk_lookup uart_lookups[] __initdata = {
{ .dev_id = "duart", },
{ .dev_id = "mxs-auart.0", },
{ .dev_id = "mxs-auart.1", },
{ .dev_id = "8006c000.serial", },
{ .dev_id = "8006e000.serial", },
{ .dev_id = "80070000.serial", },
};
static struct clk_lookup hbus_lookups[] __initdata = {
{ .dev_id = "imx23-dma-apbh", },
{ .dev_id = "80004000.dma-apbh", },
};
static struct clk_lookup xbus_lookups[] __initdata = {
{ .dev_id = "duart", .con_id = "apb_pclk"},
{ .dev_id = "80070000.serial", .con_id = "apb_pclk"},
{ .dev_id = "imx23-dma-apbx", },
{ .dev_id = "80024000.dma-apbx", },
};
static struct clk_lookup ssp_lookups[] __initdata = {
{ .dev_id = "imx23-mmc.0", },
{ .dev_id = "imx23-mmc.1", },
{ .dev_id = "80010000.ssp", },
{ .dev_id = "80034000.ssp", },
};
static struct clk_lookup lcdif_lookups[] __initdata = {
{ .dev_id = "imx23-fb", },
{ .dev_id = "80030000.lcdif", },
};
static struct clk_lookup gpmi_lookups[] __initdata = {
{ .dev_id = "imx23-gpmi-nand", },
{ .dev_id = "8000c000.gpmi", },
};
static const char *sel_pll[] __initconst = { "pll", "ref_xtal", };
static const char *sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", };
static const char *sel_pix[] __initconst = { "ref_pix", "ref_xtal", };
static const char *sel_io[] __initconst = { "ref_io", "ref_xtal", };
static const char *cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
static const char *emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
enum imx23_clk {
ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel,
lcdif_sel, gpmi_sel, ssp_sel, emi_sel, cpu, etm_sel, cpu_pll,
cpu_xtal, hbus, xbus, lcdif_div, ssp_div, gpmi_div, emi_pll,
emi_xtal, etm_div, saif_div, clk32k_div, rtc, adc, spdif_div,
clk32k, dri, pwm, filt, uart, ssp, gpmi, spdif, emi, saif,
lcdif, etm, usb, usb_pwr,
clk_max
};
static struct clk *clks[clk_max];
static enum imx23_clk clks_init_on[] __initdata = {
cpu, hbus, xbus, emi, uart,
};
int __init mx23_clocks_init(void)
{
int i;
clk_misc_init();
clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
clks[pll] = mxs_clk_pll("pll", "ref_xtal", PLLCTRL0, 16, 480000000);
clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll", FRAC, 0);
clks[ref_emi] = mxs_clk_ref("ref_emi", "pll", FRAC, 1);
clks[ref_pix] = mxs_clk_ref("ref_pix", "pll", FRAC, 2);
clks[ref_io] = mxs_clk_ref("ref_io", "pll", FRAC, 3);
clks[saif_sel] = mxs_clk_mux("saif_sel", CLKSEQ, 0, 1, sel_pll, ARRAY_SIZE(sel_pll));
clks[lcdif_sel] = mxs_clk_mux("lcdif_sel", CLKSEQ, 1, 1, sel_pix, ARRAY_SIZE(sel_pix));
clks[gpmi_sel] = mxs_clk_mux("gpmi_sel", CLKSEQ, 4, 1, sel_io, ARRAY_SIZE(sel_io));
clks[ssp_sel] = mxs_clk_mux("ssp_sel", CLKSEQ, 5, 1, sel_io, ARRAY_SIZE(sel_io));
clks[emi_sel] = mxs_clk_mux("emi_sel", CLKSEQ, 6, 1, emi_sels, ARRAY_SIZE(emi_sels));
clks[cpu] = mxs_clk_mux("cpu", CLKSEQ, 7, 1, cpu_sels, ARRAY_SIZE(cpu_sels));
clks[etm_sel] = mxs_clk_mux("etm_sel", CLKSEQ, 8, 1, sel_cpu, ARRAY_SIZE(sel_cpu));
clks[cpu_pll] = mxs_clk_div("cpu_pll", "ref_cpu", CPU, 0, 6, 28);
clks[cpu_xtal] = mxs_clk_div("cpu_xtal", "ref_xtal", CPU, 16, 10, 29);
clks[hbus] = mxs_clk_div("hbus", "cpu", HBUS, 0, 5, 29);
clks[xbus] = mxs_clk_div("xbus", "ref_xtal", XBUS, 0, 10, 31);
clks[lcdif_div] = mxs_clk_div("lcdif_div", "lcdif_sel", PIX, 0, 12, 29);
clks[ssp_div] = mxs_clk_div("ssp_div", "ssp_sel", SSP, 0, 9, 29);
clks[gpmi_div] = mxs_clk_div("gpmi_div", "gpmi_sel", GPMI, 0, 10, 29);
clks[emi_pll] = mxs_clk_div("emi_pll", "ref_emi", EMI, 0, 6, 28);
clks[emi_xtal] = mxs_clk_div("emi_xtal", "ref_xtal", EMI, 8, 4, 29);
clks[etm_div] = mxs_clk_div("etm_div", "etm_sel", ETM, 0, 6, 29);
clks[saif_div] = mxs_clk_frac("saif_div", "saif_sel", SAIF, 0, 16, 29);
clks[clk32k_div] = mxs_clk_fixed_factor("clk32k_div", "ref_xtal", 1, 750);
clks[rtc] = mxs_clk_fixed_factor("rtc", "ref_xtal", 1, 768);
clks[adc] = mxs_clk_fixed_factor("adc", "clk32k", 1, 16);
clks[spdif_div] = mxs_clk_fixed_factor("spdif_div", "pll", 1, 4);
clks[clk32k] = mxs_clk_gate("clk32k", "clk32k_div", XTAL, 26);
clks[dri] = mxs_clk_gate("dri", "ref_xtal", XTAL, 28);
clks[pwm] = mxs_clk_gate("pwm", "ref_xtal", XTAL, 29);
clks[filt] = mxs_clk_gate("filt", "ref_xtal", XTAL, 30);
clks[uart] = mxs_clk_gate("uart", "ref_xtal", XTAL, 31);
clks[ssp] = mxs_clk_gate("ssp", "ssp_div", SSP, 31);
clks[gpmi] = mxs_clk_gate("gpmi", "gpmi_div", GPMI, 31);
clks[spdif] = mxs_clk_gate("spdif", "spdif_div", SPDIF, 31);
clks[emi] = mxs_clk_gate("emi", "emi_sel", EMI, 31);
clks[saif] = mxs_clk_gate("saif", "saif_div", SAIF, 31);
clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", PIX, 31);
clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31);
clks[usb] = mxs_clk_gate("usb", "usb_pwr", DIGCTRL, 2);
clks[usb_pwr] = clk_register_gate(NULL, "usb_pwr", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock);
for (i = 0; i < ARRAY_SIZE(clks); i++)
if (IS_ERR(clks[i])) {
pr_err("i.MX23 clk %d: register failed with %ld\n",
i, PTR_ERR(clks[i]));
return PTR_ERR(clks[i]);
}
clk_register_clkdev(clks[clk32k], NULL, "timrot");
clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups));
clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups));
clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups));
clk_register_clkdevs(clks[ssp], ssp_lookups, ARRAY_SIZE(ssp_lookups));
clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups));
clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups));
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clks[clks_init_on[i]]);
mxs_timer_init(MX23_INT_TIMER0);
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/err.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/spinlock.h>
DEFINE_SPINLOCK(mxs_lock);
int mxs_clk_wait(void __iomem *reg, u8 shift)
{
unsigned long timeout = jiffies + msecs_to_jiffies(10);
while (readl_relaxed(reg) & (1 << shift))
if (time_after(jiffies, timeout))
return -ETIMEDOUT;
return 0;
}
This diff is collapsed.
......@@ -238,6 +238,7 @@ config IMX_DMA
config MXS_DMA
bool "MXS DMA support"
depends on SOC_IMX23 || SOC_IMX28
select STMP_DEVICE
select DMA_ENGINE
help
Support the MXS DMA engine. This engine including APBH-DMA
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment