ARM: driver specific updates

These are all specific to some driver. They are typically the platform
 side of a change in the drivers directory, such as adding a new driver
 or extending the interface to the platform. In cases where there is no
 maintainer for the driver, or the maintainer prefers to have the
 platform changes in the same branch as the driver changes, the patches
 to the drivers are included as well.
 
 A much smaller set of driver updates that depend on other branches
 getting merged first will be sent later.
 
 The new export of tegra_chip_uid conflicts with other changes in fuse.c.
 In rtc-sa1100.c, the global removal of IRQF_DISABLED conflicts with
 the cleanup of the interrupt handling of that driver.
 
 Signed-off-by: Arnd Bergmann <arnd@arndb.de>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIVAwUAT24/Y2CrR//JCVInAQLUdw//V4pKPuKempSe1kuD2MJfqldHwEVOlAUt
 of1IhLPAp8tpCscPDQ0yTy3ixquINg4jVnaDLL+E0quVbhLu6hlS2TYNKDEaVAAc
 cPUtVEUdja7Cfu4+bXX2vcWM/UyI6Ax7bsUUcwu4wFnEsjA6qOSu/jYY4jXDguHq
 ODGQSaSz0XQkfVBsWOlO8W/ejb0T3y+Ro3M/Vz5qJsMnZBR8R/i9aUYDFGiZ1GTn
 3APHB7ALz6SS5/9SJS65PH16poBexcea5gyb3gnR1yt30kRmMTOAWrLC+JdyqFaO
 7LHXW514+D1QbWV2gwNCWhQSLbgp9PWq/FXJtq4StW7tgNbDbj1d1Dc1GX+fvk2M
 bBih1yWoIVx6CZWFBQ7gsbqVHUZ/sW2fo76yb8K5dVPXx0fL5lEkv5Xwk3gxbqt5
 lPE8+z+jiL5D+8RK1DZQu1PfxzaMwDZkJkVoGLCcdyM7FvnX3LIYf2bqbcp+zrQL
 lz9aht9C1k12R7feOX8emlluNd3eaKv/6jLrOasUP5wrJDam5hesSD5mLeTlAdxZ
 U8XJe4L24dFv15/yrMCzcyes5EmB3aS3nfb9TsSfq22IOKo2PCQLCnL6Z/rfM+1p
 mGu7BqdBnx3/8NkHdUrttMWjuPNh77MfPM6RO/E+TaBLHtwvKoLWJAHAYQNmt2xH
 IbGcyorBD5s=
 =pQ3X
 -----END PGP SIGNATURE-----

Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull "ARM: driver specific updates" from Arnd Bergmann:
 "These are all specific to some driver.  They are typically the
  platform side of a change in the drivers directory, such as adding a
  new driver or extending the interface to the platform.  In cases where
  there is no maintainer for the driver, or the maintainer prefers to
  have the platform changes in the same branch as the driver changes,
  the patches to the drivers are included as well.

  A much smaller set of driver updates that depend on other branches
  getting merged first will be sent later.

  The new export of tegra_chip_uid conflicts with other changes in
  fuse.c.  In rtc-sa1100.c, the global removal of IRQF_DISABLED
  conflicts with the cleanup of the interrupt handling of that driver.

  Signed-off-by: Arnd Bergmann <arnd@arndb.de>"

Fixed up aforementioned trivial conflicts.

* tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (94 commits)
  ARM: SAMSUNG: change the name from s3c-sdhci to exynos4-sdhci
  mmc: sdhci-s3c: add platform data for the second capability
  ARM: SAMSUNG: support the second capability for samsung-soc
  ARM: EXYNOS: add support DMA for EXYNOS4X12 SoC
  ARM: EXYNOS: Add apb_pclk clkdev entry for mdma1
  ARM: EXYNOS: Enable MDMA driver
  regulator: Remove bq24022 regulator driver
  rtc: sa1100: add OF support
  pxa: magician/hx4700: Convert to gpio-regulator from bq24022
  ARM: OMAP3+: SmartReflex: fix error handling
  ARM: OMAP3+: SmartReflex: fix the use of debugfs_create_* API
  ARM: OMAP3+: SmartReflex: micro-optimization for sanity check
  ARM: OMAP3+: SmartReflex: misc cleanups
  ARM: OMAP3+: SmartReflex: move late_initcall() closer to its argument
  ARM: OMAP3+: SmartReflex: add missing platform_set_drvdata()
  ARM: OMAP3+: hwmod: add SmartReflex IRQs
  ARM: OMAP3+: SmartReflex: clear ERRCONFIG_VPBOUNDINTST only on a need
  ARM: OMAP3+: SmartReflex: Fix status masking in ERRCONFIG register
  ARM: OMAP3+: SmartReflex: Add a shutdown hook
  ARM: OMAP3+: SmartReflex Class3: disable errorgen before disable VP
  ...

Conflicts:
	arch/arm/mach-tegra/Makefile
	arch/arm/mach-tegra/fuse.c
	drivers/rtc/rtc-sa1100.c
This commit is contained in:
Linus Torvalds 2012-03-27 16:41:24 -07:00
commit 34800598b2
118 changed files with 3077 additions and 732 deletions

View File

@ -0,0 +1,100 @@
Embedded Memory Controller
Properties:
- name : Should be emc
- #address-cells : Should be 1
- #size-cells : Should be 0
- compatible : Should contain "nvidia,tegra20-emc".
- reg : Offset and length of the register set for the device
- nvidia,use-ram-code : If present, the sub-nodes will be addressed
and chosen using the ramcode board selector. If omitted, only one
set of tables can be present and said tables will be used
irrespective of ram-code configuration.
Child device nodes describe the memory settings for different configurations and clock rates.
Example:
emc@7000f400 {
#address-cells = < 1 >;
#size-cells = < 0 >;
compatible = "nvidia,tegra20-emc";
reg = <0x7000f4000 0x200>;
}
Embedded Memory Controller ram-code table
If the emc node has the nvidia,use-ram-code property present, then the
next level of nodes below the emc table are used to specify which settings
apply for which ram-code settings.
If the emc node lacks the nvidia,use-ram-code property, this level is omitted
and the tables are stored directly under the emc node (see below).
Properties:
- name : Should be emc-tables
- nvidia,ram-code : the binary representation of the ram-code board strappings
for which this node (and children) are valid.
Embedded Memory Controller configuration table
This is a table containing the EMC register settings for the various
operating speeds of the memory controller. They are always located as
subnodes of the emc controller node.
There are two ways of specifying which tables to use:
* The simplest is if there is just one set of tables in the device tree,
and they will always be used (based on which frequency is used).
This is the preferred method, especially when firmware can fill in
this information based on the specific system information and just
pass it on to the kernel.
* The slightly more complex one is when more than one memory configuration
might exist on the system. The Tegra20 platform handles this during
early boot by selecting one out of possible 4 memory settings based
on a 2-pin "ram code" bootstrap setting on the board. The values of
these strappings can be read through a register in the SoC, and thus
used to select which tables to use.
Properties:
- name : Should be emc-table
- compatible : Should contain "nvidia,tegra20-emc-table".
- reg : either an opaque enumerator to tell different tables apart, or
the valid frequency for which the table should be used (in kHz).
- clock-frequency : the clock frequency for the EMC at which this
table should be used (in kHz).
- nvidia,emc-registers : a 46 word array of EMC registers to be programmed
for operation at the 'clock-frequency' setting.
The order and contents of the registers are:
RC, RFC, RAS, RP, R2W, W2R, R2P, W2P, RD_RCD, WR_RCD, RRD, REXT,
WDV, QUSE, QRST, QSAFE, RDV, REFRESH, BURST_REFRESH_NUM, PDEX2WR,
PDEX2RD, PCHG2PDEN, ACT2PDEN, AR2PDEN, RW2PDEN, TXSR, TCKE, TFAW,
TRPAB, TCLKSTABLE, TCLKSTOP, TREFBW, QUSE_EXTRA, FBIO_CFG6, ODT_WRITE,
ODT_READ, FBIO_CFG5, CFG_DIG_DLL, DLL_XFORM_DQS, DLL_XFORM_QUSE,
ZCAL_REF_CNT, ZCAL_WAIT_CNT, AUTO_CAL_INTERVAL, CFG_CLKTRIM_0,
CFG_CLKTRIM_1, CFG_CLKTRIM_2
emc-table@166000 {
reg = <166000>;
compatible = "nvidia,tegra20-emc-table";
clock-frequency = < 166000 >;
nvidia,emc-registers = < 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 >;
};
emc-table@333000 {
reg = <333000>;
compatible = "nvidia,tegra20-emc-table";
clock-frequency = < 333000 >;
nvidia,emc-registers = < 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 >;
};

View File

@ -0,0 +1,19 @@
NVIDIA Tegra Power Management Controller (PMC)
Properties:
- name : Should be pmc
- compatible : Should contain "nvidia,tegra<chip>-pmc".
- reg : Offset and length of the register set for the device
- nvidia,invert-interrupt : If present, inverts the PMU interrupt signal.
The PMU is an external Power Management Unit, whose interrupt output
signal is fed into the PMC. This signal is optionally inverted, and then
fed into the ARM GIC. The PMC is not involved in the detection or
handling of this interrupt signal, merely its inversion.
Example:
pmc@7000f400 {
compatible = "nvidia,tegra20-pmc";
reg = <0x7000e400 0x400>;
nvidia,invert-interrupt;
};

View File

@ -0,0 +1,30 @@
* NVIDIA Tegra APB DMA controller
Required properties:
- compatible: Should be "nvidia,<chip>-apbdma"
- reg: Should contain DMA registers location and length. This shuld include
all of the per-channel registers.
- interrupts: Should contain all of the per-channel DMA interrupts.
Examples:
apbdma: dma@6000a000 {
compatible = "nvidia,tegra20-apbdma";
reg = <0x6000a000 0x1200>;
interrupts = < 0 136 0x04
0 137 0x04
0 138 0x04
0 139 0x04
0 140 0x04
0 141 0x04
0 142 0x04
0 143 0x04
0 144 0x04
0 145 0x04
0 146 0x04
0 147 0x04
0 148 0x04
0 149 0x04
0 150 0x04
0 151 0x04 >;
};

View File

@ -1,8 +1,40 @@
NVIDIA Tegra 2 GPIO controller
NVIDIA Tegra GPIO controller
Required properties:
- compatible : "nvidia,tegra20-gpio"
- compatible : "nvidia,tegra<chip>-gpio"
- reg : Physical base address and length of the controller's registers.
- interrupts : The interrupt outputs from the controller. For Tegra20,
there should be 7 interrupts specified, and for Tegra30, there should
be 8 interrupts specified.
- #gpio-cells : Should be two. The first cell is the pin number and the
second cell is used to specify optional parameters:
- bit 0 specifies polarity (0 for normal, 1 for inverted)
- gpio-controller : Marks the device node as a GPIO controller.
- #interrupt-cells : Should be 2.
The first cell is the GPIO number.
The second cell is used to specify flags:
bits[3:0] 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.
Valid combinations are 1, 2, 3, 4, 8.
- interrupt-controller : Marks the device node as an interrupt controller.
Example:
gpio: gpio@6000d000 {
compatible = "nvidia,tegra20-gpio";
reg = < 0x6000d000 0x1000 >;
interrupts = < 0 32 0x04
0 33 0x04
0 34 0x04
0 35 0x04
0 55 0x04
0 87 0x04
0 89 0x04 >;
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
};

View File

@ -760,7 +760,7 @@ config ARCH_SA1100
select ARCH_HAS_CPUFREQ
select CPU_FREQ
select GENERIC_CLOCKEVENTS
select HAVE_CLK
select CLKDEV_LOOKUP
select HAVE_SCHED_CLOCK
select TICK_ONESHOT
select ARCH_REQUIRE_GPIOLIB

View File

@ -180,12 +180,12 @@ choice
Say Y here if you want kernel low-level debugging support
on i.MX50 or i.MX53.
config DEBUG_IMX6Q_UART
bool "i.MX6Q Debug UART"
config DEBUG_IMX6Q_UART4
bool "i.MX6Q Debug UART4"
depends on SOC_IMX6Q
help
Say Y here if you want kernel low-level debugging support
on i.MX6Q.
on i.MX6Q UART4.
config DEBUG_MSM_UART1
bool "Kernel low-level debugging messages via MSM UART1"

View File

@ -10,19 +10,25 @@
reg = < 0x00000000 0x40000000 >;
};
pmc@7000f400 {
nvidia,invert-interrupt;
};
i2c@7000c000 {
clock-frequency = <400000>;
codec: wm8903@1a {
wm8903: wm8903@1a {
compatible = "wlf,wm8903";
reg = <0x1a>;
interrupts = < 347 >;
interrupt-parent = <&gpio>;
interrupts = < 187 0x04 >;
gpio-controller;
#gpio-cells = <2>;
/* 0x8000 = Not configured */
gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >;
micdet-cfg = <0>;
micdet-delay = <100>;
gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
};
};
@ -38,13 +44,32 @@
clock-frequency = <400000>;
};
sound {
compatible = "nvidia,harmony-sound", "nvidia,tegra-wm8903";
i2s@70002a00 {
status = "disable";
};
spkr-en-gpios = <&codec 2 0>;
hp-det-gpios = <&gpio 178 0>;
int-mic-en-gpios = <&gpio 184 0>;
ext-mic-en-gpios = <&gpio 185 0>;
sound {
compatible = "nvidia,tegra-audio-wm8903-harmony",
"nvidia,tegra-audio-wm8903";
nvidia,model = "NVIDIA Tegra Harmony";
nvidia,audio-routing =
"Headphone Jack", "HPOUTR",
"Headphone Jack", "HPOUTL",
"Int Spk", "ROP",
"Int Spk", "RON",
"Int Spk", "LOP",
"Int Spk", "LON",
"Mic Jack", "MICBIAS",
"IN1L", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&wm8903>;
nvidia,spkr-en-gpios = <&wm8903 2 0>;
nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
};
serial@70006000 {

View File

@ -12,6 +12,13 @@
i2c@7000c000 {
clock-frequency = <400000>;
alc5632: alc5632@1e {
compatible = "realtek,alc5632";
reg = <0x1e>;
gpio-controller;
#gpio-cells = <2>;
};
};
i2c@7000c400 {
@ -42,6 +49,29 @@
};
};
i2s@70002a00 {
status = "disable";
};
sound {
compatible = "nvidia,tegra-audio-alc5632-paz00",
"nvidia,tegra-audio-alc5632";
nvidia,model = "Compal PAZ00";
nvidia,audio-routing =
"Int Spk", "SPKOUT",
"Int Spk", "SPKOUTN",
"Headset Mic", "MICBIAS1",
"MIC1", "Headset Mic",
"Headset Stereophone", "HPR",
"Headset Stereophone", "HPL";
nvidia,audio-codec = <&alc5632>;
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
};
serial@70006000 {
clock-frequency = <216000000>;
};

View File

@ -13,6 +13,20 @@
i2c@7000c000 {
clock-frequency = <400000>;
wm8903: wm8903@1a {
compatible = "wlf,wm8903";
reg = <0x1a>;
interrupt-parent = <&gpio>;
interrupts = < 187 0x04 >;
gpio-controller;
#gpio-cells = <2>;
micdet-cfg = <0>;
micdet-delay = <100>;
gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
};
};
i2c@7000c400 {
@ -32,6 +46,32 @@
};
};
i2s@70002a00 {
status = "disable";
};
sound {
compatible = "nvidia,tegra-audio-wm8903-seaboard",
"nvidia,tegra-audio-wm8903";
nvidia,model = "NVIDIA Tegra Seaboard";
nvidia,audio-routing =
"Headphone Jack", "HPOUTR",
"Headphone Jack", "HPOUTL",
"Int Spk", "ROP",
"Int Spk", "RON",
"Int Spk", "LOP",
"Int Spk", "LON",
"Mic Jack", "MICBIAS",
"IN1R", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&wm8903>;
nvidia,spkr-en-gpios = <&wm8903 2 0>;
nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */
};
serial@70006000 {
status = "disable";
};
@ -93,4 +133,42 @@
gpio-key,wakeup;
};
};
emc@7000f400 {
emc-table@190000 {
reg = < 190000 >;
compatible = "nvidia,tegra20-emc-table";
clock-frequency = < 190000 >;
nvidia,emc-registers = < 0x0000000c 0x00000026
0x00000009 0x00000003 0x00000004 0x00000004
0x00000002 0x0000000c 0x00000003 0x00000003
0x00000002 0x00000001 0x00000004 0x00000005
0x00000004 0x00000009 0x0000000d 0x0000059f
0x00000000 0x00000003 0x00000003 0x00000003
0x00000003 0x00000001 0x0000000b 0x000000c8
0x00000003 0x00000007 0x00000004 0x0000000f
0x00000002 0x00000000 0x00000000 0x00000002
0x00000000 0x00000000 0x00000083 0xa06204ae
0x007dc010 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 >;
};
emc-table@380000 {
reg = < 380000 >;
compatible = "nvidia,tegra20-emc-table";
clock-frequency = < 380000 >;
nvidia,emc-registers = < 0x00000017 0x0000004b
0x00000012 0x00000006 0x00000004 0x00000005
0x00000003 0x0000000c 0x00000006 0x00000006
0x00000003 0x00000001 0x00000004 0x00000005
0x00000004 0x00000009 0x0000000d 0x00000b5f
0x00000000 0x00000003 0x00000003 0x00000006
0x00000006 0x00000001 0x00000011 0x000000c8
0x00000003 0x0000000e 0x00000007 0x0000000f
0x00000002 0x00000000 0x00000000 0x00000002
0x00000000 0x00000000 0x00000083 0xe044048b
0x007d8010 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 >;
};
};
};

View File

@ -26,6 +26,18 @@
status = "disable";
};
i2s@70002800 {
status = "disable";
};
i2s@70002a00 {
status = "disable";
};
das@70000c00 {
status = "disable";
};
serial@70006000 {
clock-frequency = < 216000000 >;
};

View File

@ -12,6 +12,20 @@
i2c@7000c000 {
clock-frequency = <400000>;
wm8903: wm8903@1a {
compatible = "wlf,wm8903";
reg = <0x1a>;
interrupt-parent = <&gpio>;
interrupts = < 187 0x04 >;
gpio-controller;
#gpio-cells = <2>;
micdet-cfg = <0>;
micdet-delay = <100>;
gpio-cfg = < 0xffffffff 0xffffffff 0 0xffffffff 0xffffffff >;
};
};
i2c@7000c400 {
@ -26,6 +40,34 @@
clock-frequency = <400000>;
};
i2s@70002a00 {
status = "disable";
};
sound {
compatible = "nvidia,tegra-audio-wm8903-ventana",
"nvidia,tegra-audio-wm8903";
nvidia,model = "NVIDIA Tegra Ventana";
nvidia,audio-routing =
"Headphone Jack", "HPOUTR",
"Headphone Jack", "HPOUTL",
"Int Spk", "ROP",
"Int Spk", "RON",
"Int Spk", "LOP",
"Int Spk", "LON",
"Mic Jack", "MICBIAS",
"IN1L", "Mic Jack";
nvidia,i2s-controller = <&tegra_i2s1>;
nvidia,audio-codec = <&wm8903>;
nvidia,spkr-en-gpios = <&wm8903 2 0>;
nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
};
serial@70006000 {
status = "disable";
};

View File

@ -4,6 +4,11 @@
compatible = "nvidia,tegra20";
interrupt-parent = <&intc>;
pmc@7000f400 {
compatible = "nvidia,tegra20-pmc";
reg = <0x7000e400 0x400>;
};
intc: interrupt-controller@50041000 {
compatible = "arm,cortex-a9-gic";
interrupt-controller;
@ -12,6 +17,27 @@
< 0x50040100 0x0100 >;
};
apbdma: dma@6000a000 {
compatible = "nvidia,tegra20-apbdma";
reg = <0x6000a000 0x1200>;
interrupts = < 0 104 0x04
0 105 0x04
0 106 0x04
0 107 0x04
0 108 0x04
0 109 0x04
0 110 0x04
0 111 0x04
0 112 0x04
0 113 0x04
0 114 0x04
0 115 0x04
0 116 0x04
0 117 0x04
0 118 0x04
0 119 0x04 >;
};
i2c@7000c000 {
#address-cells = <1>;
#size-cells = <0>;
@ -44,18 +70,18 @@
interrupts = < 0 53 0x04 >;
};
i2s@70002800 {
tegra_i2s1: i2s@70002800 {
compatible = "nvidia,tegra20-i2s";
reg = <0x70002800 0x200>;
interrupts = < 0 13 0x04 >;
dma-channel = < 2 >;
nvidia,dma-request-selector = < &apbdma 2 >;
};
i2s@70002a00 {
tegra_i2s2: i2s@70002a00 {
compatible = "nvidia,tegra20-i2s";
reg = <0x70002a00 0x200>;
interrupts = < 0 3 0x04 >;
dma-channel = < 1 >;
nvidia,dma-request-selector = < &apbdma 1 >;
};
das@70000c00 {
@ -75,6 +101,8 @@
0 89 0x04 >;
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
};
pinmux: pinmux@70000000 {
@ -120,6 +148,13 @@
interrupts = < 0 91 0x04 >;
};
emc@7000f400 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-emc";
reg = <0x7000f400 0x200>;
};
sdhci@c8000000 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000000 0x200>;

View File

@ -4,6 +4,11 @@
compatible = "nvidia,tegra30";
interrupt-parent = <&intc>;
pmc@7000f400 {
compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc";
reg = <0x7000e400 0x400>;
};
intc: interrupt-controller@50041000 {
compatible = "arm,cortex-a9-gic";
interrupt-controller;
@ -12,6 +17,43 @@
< 0x50040100 0x0100 >;
};
apbdma: dma@6000a000 {
compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
reg = <0x6000a000 0x1400>;
interrupts = < 0 104 0x04
0 105 0x04
0 106 0x04
0 107 0x04
0 108 0x04
0 109 0x04
0 110 0x04
0 111 0x04
0 112 0x04
0 113 0x04
0 114 0x04
0 115 0x04
0 116 0x04
0 117 0x04
0 118 0x04
0 119 0x04
0 128 0x04
0 129 0x04
0 130 0x04
0 131 0x04
0 132 0x04
0 133 0x04
0 134 0x04
0 135 0x04
0 136 0x04
0 137 0x04
0 138 0x04
0 139 0x04
0 140 0x04
0 141 0x04
0 142 0x04
0 143 0x04 >;
};
i2c@7000c000 {
#address-cells = <1>;
#size-cells = <0>;
@ -55,9 +97,18 @@
gpio: gpio@6000d000 {
compatible = "nvidia,tegra30-gpio", "nvidia,tegra20-gpio";
reg = < 0x6000d000 0x1000 >;
interrupts = < 0 32 0x04 0 33 0x04 0 34 0x04 0 35 0x04 0 55 0x04 0 87 0x04 0 89 0x04 >;
interrupts = < 0 32 0x04
0 33 0x04
0 34 0x04
0 35 0x04
0 55 0x04
0 87 0x04
0 89 0x04
0 125 0x04 >;
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
};
serial@70006000 {

View File

@ -45,6 +45,7 @@ CONFIG_FPE_NWFPE=y
CONFIG_FPE_NWFPE_XP=y
CONFIG_PM_DEBUG=y
CONFIG_NET=y
CONFIG_SMSC911X=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
@ -79,6 +80,8 @@ CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_AT25=y
CONFIG_NETDEVICES=y
CONFIG_CS89x0=y
CONFIG_CS89x0_PLATFORM=y
CONFIG_DM9000=y
CONFIG_SMC91X=y
CONFIG_SMC911X=y
@ -116,6 +119,21 @@ CONFIG_FB_IMX=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_LCD_L4F00242T03=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_COMMON=y
CONFIG_VIDEO_MEDIA=y
CONFIG_VIDEO_V4L2=y
CONFIG_VIDEOBUF_GEN=y
CONFIG_VIDEOBUF_DMA_CONTIG=y
CONFIG_VIDEOBUF2_CORE=y
CONFIG_VIDEO_CAPTURE_DRIVERS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_SOC_CAMERA=y
CONFIG_SOC_CAMERA_OV2640=y
CONFIG_VIDEO_MX2_HOSTSUPPORT=y
CONFIG_VIDEO_MX2=y
CONFIG_BACKLIGHT_PWM=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FONTS=y

View File

@ -81,6 +81,8 @@ CONFIG_PATA_IMX=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
CONFIG_CS89x0=y
CONFIG_CS89x0_PLATFORM=y
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
@ -125,7 +127,39 @@ CONFIG_IMX2_WDT=y
CONFIG_MFD_MC13XXX=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_MC13783=y
CONFIG_REGULATOR_MC13892=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_V4L2=y
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_COMMON=y
CONFIG_VIDEOBUF_GEN=y
CONFIG_VIDEOBUF2_CORE=y
CONFIG_VIDEOBUF2_MEMOPS=y
CONFIG_VIDEOBUF2_DMA_CONTIG=y
CONFIG_VIDEO_CAPTURE_DRIVERS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_SOC_CAMERA=y
CONFIG_SOC_CAMERA_OV2640=y
CONFIG_MX3_VIDEO=y
CONFIG_VIDEO_MX3=y
CONFIG_FB=y
CONFIG_FB_MX3=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_L4F00242T03=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_GENERIC=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MXC=y

View File

@ -101,7 +101,7 @@ CONFIG_MFD_ASIC3=y
CONFIG_HTC_EGPIO=y
CONFIG_HTC_PASIC3=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_BQ24022=y
CONFIG_REGULATOR_GPIO=y
CONFIG_FB=y
CONFIG_FB_PXA=y
CONFIG_FB_PXA_OVERLAY=y

View File

@ -891,7 +891,8 @@ static struct platform_device at91sam9263_isi_device = {
.num_resources = ARRAY_SIZE(isi_resources),
};
void __init at91_add_device_isi(void)
void __init at91_add_device_isi(struct isi_platform_data *data,
bool use_pck_as_mck)
{
at91_set_A_periph(AT91_PIN_PE0, 0); /* ISI_D0 */
at91_set_A_periph(AT91_PIN_PE1, 0); /* ISI_D1 */
@ -904,14 +905,20 @@ void __init at91_add_device_isi(void)
at91_set_A_periph(AT91_PIN_PE8, 0); /* ISI_PCK */
at91_set_A_periph(AT91_PIN_PE9, 0); /* ISI_HSYNC */
at91_set_A_periph(AT91_PIN_PE10, 0); /* ISI_VSYNC */
at91_set_B_periph(AT91_PIN_PE11, 0); /* ISI_MCK (PCK3) */
at91_set_B_periph(AT91_PIN_PE12, 0); /* ISI_PD8 */
at91_set_B_periph(AT91_PIN_PE13, 0); /* ISI_PD9 */
at91_set_B_periph(AT91_PIN_PE14, 0); /* ISI_PD10 */
at91_set_B_periph(AT91_PIN_PE15, 0); /* ISI_PD11 */
if (use_pck_as_mck) {
at91_set_B_periph(AT91_PIN_PE11, 0); /* ISI_MCK (PCK3) */
/* TODO: register the PCK for ISI_MCK and set its parent */
}
}
#else
void __init at91_add_device_isi(void) {}
void __init at91_add_device_isi(struct isi_platform_data *data,
bool use_pck_as_mck) {}
#endif

View File

@ -14,6 +14,7 @@
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
#include <linux/atmel-mci.h>
@ -28,7 +29,10 @@
#include <mach/at_hdmac.h>
#include <mach/atmel-mci.h>
#include <media/atmel-isi.h>
#include "generic.h"
#include "clock.h"
/* --------------------------------------------------------------------
@ -870,6 +874,96 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data)
void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
#endif
/* --------------------------------------------------------------------
* Image Sensor Interface
* -------------------------------------------------------------------- */
#if defined(CONFIG_VIDEO_ATMEL_ISI) || defined(CONFIG_VIDEO_ATMEL_ISI_MODULE)
static u64 isi_dmamask = DMA_BIT_MASK(32);
static struct isi_platform_data isi_data;
struct resource isi_resources[] = {
[0] = {
.start = AT91SAM9G45_BASE_ISI,
.end = AT91SAM9G45_BASE_ISI + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91SAM9G45_ID_ISI,
.end = AT91SAM9G45_ID_ISI,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device at91sam9g45_isi_device = {
.name = "atmel_isi",
.id = 0,
.dev = {
.dma_mask = &isi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &isi_data,
},
.resource = isi_resources,
.num_resources = ARRAY_SIZE(isi_resources),
};
static struct clk_lookup isi_mck_lookups[] = {
CLKDEV_CON_DEV_ID("isi_mck", "atmel_isi.0", NULL),
};
void __init at91_add_device_isi(struct isi_platform_data *data,
bool use_pck_as_mck)
{
struct clk *pck;
struct clk *parent;
if (!data)
return;
isi_data = *data;
at91_set_A_periph(AT91_PIN_PB20, 0); /* ISI_D0 */
at91_set_A_periph(AT91_PIN_PB21, 0); /* ISI_D1 */
at91_set_A_periph(AT91_PIN_PB22, 0); /* ISI_D2 */
at91_set_A_periph(AT91_PIN_PB23, 0); /* ISI_D3 */
at91_set_A_periph(AT91_PIN_PB24, 0); /* ISI_D4 */
at91_set_A_periph(AT91_PIN_PB25, 0); /* ISI_D5 */
at91_set_A_periph(AT91_PIN_PB26, 0); /* ISI_D6 */
at91_set_A_periph(AT91_PIN_PB27, 0); /* ISI_D7 */
at91_set_A_periph(AT91_PIN_PB28, 0); /* ISI_PCK */
at91_set_A_periph(AT91_PIN_PB30, 0); /* ISI_HSYNC */
at91_set_A_periph(AT91_PIN_PB29, 0); /* ISI_VSYNC */
at91_set_B_periph(AT91_PIN_PB8, 0); /* ISI_PD8 */
at91_set_B_periph(AT91_PIN_PB9, 0); /* ISI_PD9 */
at91_set_B_periph(AT91_PIN_PB10, 0); /* ISI_PD10 */
at91_set_B_periph(AT91_PIN_PB11, 0); /* ISI_PD11 */
platform_device_register(&at91sam9g45_isi_device);
if (use_pck_as_mck) {
at91_set_B_periph(AT91_PIN_PB31, 0); /* ISI_MCK (PCK1) */
pck = clk_get(NULL, "pck1");
parent = clk_get(NULL, "plla");
BUG_ON(IS_ERR(pck) || IS_ERR(parent));
if (clk_set_parent(pck, parent)) {
pr_err("Failed to set PCK's parent\n");
} else {
/* Register PCK as ISI_MCK */
isi_mck_lookups[0].clk = pck;
clkdev_add_table(isi_mck_lookups,
ARRAY_SIZE(isi_mck_lookups));
}
clk_put(pck);
clk_put(parent);
}
}
#else
void __init at91_add_device_isi(struct isi_platform_data *data,
bool use_pck_as_mck) {}
#endif
/* --------------------------------------------------------------------
* LCD Controller

View File

@ -1,7 +1,7 @@
/*
* linux/arch/arm/mach-at91/board-flexibity.c
*
* Copyright (C) 2010 Flexibity
* Copyright (C) 2010-2011 Flexibity
* Copyright (C) 2005 SAN People
* Copyright (C) 2006 Atmel
*
@ -62,6 +62,13 @@ static struct at91_udc_data __initdata flexibity_udc_data = {
.pullup_pin = -EINVAL, /* pull-up driven by UDC */
};
/* I2C devices */
static struct i2c_board_info __initdata flexibity_i2c_devices[] = {
{
I2C_BOARD_INFO("ds1307", 0x68),
},
};
/* SPI devices */
static struct spi_board_info flexibity_spi_devices[] = {
{ /* DataFlash chip */
@ -141,6 +148,9 @@ static void __init flexibity_board_init(void)
at91_add_device_usbh(&flexibity_usbh_data);
/* USB Device */
at91_add_device_udc(&flexibity_udc_data);
/* I2C */
at91_add_device_i2c(flexibity_i2c_devices,
ARRAY_SIZE(flexibity_i2c_devices));
/* SPI */
at91_add_device_spi(flexibity_spi_devices,
ARRAY_SIZE(flexibity_spi_devices));

View File

@ -24,11 +24,13 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/leds.h>
#include <linux/clk.h>
#include <linux/atmel-mci.h>
#include <linux/delay.h>
#include <mach/hardware.h>
#include <video/atmel_lcdc.h>
#include <media/soc_camera.h>
#include <media/atmel-isi.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@ -184,6 +186,71 @@ static void __init ek_add_device_nand(void)
}
/*
* ISI
*/
static struct isi_platform_data __initdata isi_data = {
.frate = ISI_CFG1_FRATE_CAPTURE_ALL,
/* to use codec and preview path simultaneously */
.full_mode = 1,
.data_width_flags = ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10,
/* ISI_MCK is provided by programmable clock or external clock */
.mck_hz = 25000000,
};
/*
* soc-camera OV2640
*/
#if defined(CONFIG_SOC_CAMERA_OV2640) || \
defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
static unsigned long isi_camera_query_bus_param(struct soc_camera_link *link)
{
/* ISI board for ek using default 8-bits connection */
return SOCAM_DATAWIDTH_8;
}
static int i2c_camera_power(struct device *dev, int on)
{
/* enable or disable the camera */
pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
at91_set_gpio_output(AT91_PIN_PD13, !on);
if (!on)
goto out;
/* If enabled, give a reset impulse */
at91_set_gpio_output(AT91_PIN_PD12, 0);
msleep(20);
at91_set_gpio_output(AT91_PIN_PD12, 1);
msleep(100);
out:
return 0;
}
static struct i2c_board_info i2c_camera = {
I2C_BOARD_INFO("ov2640", 0x30),
};
static struct soc_camera_link iclink_ov2640 = {
.bus_id = 0,
.board_info = &i2c_camera,
.i2c_adapter_id = 0,
.power = i2c_camera_power,
.query_bus_param = isi_camera_query_bus_param,
};
static struct platform_device isi_ov2640 = {
.name = "soc-camera-pdrv",
.id = 0,
.dev = {
.platform_data = &iclink_ov2640,
},
};
#endif
/*
* LCD Controller
*/
@ -377,7 +444,12 @@ static struct gpio_led ek_pwm_led[] = {
#endif
};
static struct platform_device *devices[] __initdata = {
#if defined(CONFIG_SOC_CAMERA_OV2640) || \
defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
&isi_ov2640,
#endif
};
static void __init ek_board_init(void)
{
@ -399,6 +471,8 @@ static void __init ek_board_init(void)
ek_add_device_nand();
/* I2C */
at91_add_device_i2c(0, NULL, 0);
/* ISI, using programmable clock as ISI_MCK */
at91_add_device_isi(&isi_data, true);
/* LCD Controller */
at91_add_device_lcdc(&ek_lcdc_data);
/* Touch Screen */
@ -410,6 +484,8 @@ static void __init ek_board_init(void)
/* LEDs */
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
/* Other platform devices */
platform_add_devices(devices, ARRAY_SIZE(devices));
}
MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")

View File

@ -107,6 +107,8 @@ struct atmel_nand_data {
u8 ale; /* address line number connected to ALE */
u8 cle; /* address line number connected to CLE */
u8 bus_width_16; /* buswidth is 16 bit */
u8 correction_cap; /* PMECC correction capability */
u16 sector_size; /* Sector size for PMECC */
struct mtd_partition *parts;
unsigned int num_parts;
};
@ -179,7 +181,9 @@ extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
/* ISI */
extern void __init at91_add_device_isi(void);
struct isi_platform_data;
extern void __init at91_add_device_isi(struct isi_platform_data *data,
bool use_pck_as_mck);
/* Touchscreen Controller */
struct at91_tsadcc_data {

View File

@ -42,6 +42,7 @@ config SOC_EXYNOS4212
bool "SAMSUNG EXYNOS4212"
default y
depends on ARCH_EXYNOS4
select SAMSUNG_DMADEV
select S5P_PM if PM
select S5P_SLEEP if PM
help
@ -51,6 +52,7 @@ config SOC_EXYNOS4412
bool "SAMSUNG EXYNOS4412"
default y
depends on ARCH_EXYNOS4
select SAMSUNG_DMADEV
help
Enable EXYNOS4412 SoC support
@ -335,6 +337,7 @@ config MACH_SMDK4212
select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_PWM
select EXYNOS4_DEV_DMA
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C3
select EXYNOS4_SETUP_I2C7

View File

@ -789,6 +789,13 @@ static struct clk exynos4_clk_pdma1 = {
.ctrlbit = (1 << 1),
};
static struct clk exynos4_clk_mdma1 = {
.name = "dma",
.devname = "dma-pl330.2",
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = ((1 << 8) | (1 << 5) | (1 << 2)),
};
struct clk *exynos4_clkset_group_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_xusbxti,
@ -1307,6 +1314,7 @@ static struct clksrc_clk *exynos4_sysclks[] = {
static struct clk *exynos4_clk_cdev[] = {
&exynos4_clk_pdma0,
&exynos4_clk_pdma1,
&exynos4_clk_mdma1,
};
static struct clksrc_clk *exynos4_clksrc_cdev[] = {
@ -1335,6 +1343,7 @@ static struct clk_lookup exynos4_clk_lookup[] = {
CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),

View File

@ -29,6 +29,7 @@
#include <asm/irq.h>
#include <plat/devs.h>
#include <plat/irqs.h>
#include <plat/cpu.h>
#include <mach/map.h>
#include <mach/irqs.h>
@ -36,7 +37,7 @@
static u64 dma_dmamask = DMA_BIT_MASK(32);
static u8 pdma0_peri[] = {
static u8 exynos4210_pdma0_peri[] = {
DMACH_PCM0_RX,
DMACH_PCM0_TX,
DMACH_PCM2_RX,
@ -69,15 +70,47 @@ static u8 pdma0_peri[] = {
DMACH_AC97_PCMOUT,
};
static struct dma_pl330_platdata exynos4_pdma0_pdata = {
.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
.peri_id = pdma0_peri,
static u8 exynos4212_pdma0_peri[] = {
DMACH_PCM0_RX,
DMACH_PCM0_TX,
DMACH_PCM2_RX,
DMACH_PCM2_TX,
DMACH_MIPI_HSI0,
DMACH_MIPI_HSI1,
DMACH_SPI0_RX,
DMACH_SPI0_TX,
DMACH_SPI2_RX,
DMACH_SPI2_TX,
DMACH_I2S0S_TX,
DMACH_I2S0_RX,
DMACH_I2S0_TX,
DMACH_I2S2_RX,
DMACH_I2S2_TX,
DMACH_UART0_RX,
DMACH_UART0_TX,
DMACH_UART2_RX,
DMACH_UART2_TX,
DMACH_UART4_RX,
DMACH_UART4_TX,
DMACH_SLIMBUS0_RX,
DMACH_SLIMBUS0_TX,
DMACH_SLIMBUS2_RX,
DMACH_SLIMBUS2_TX,
DMACH_SLIMBUS4_RX,
DMACH_SLIMBUS4_TX,
DMACH_AC97_MICIN,
DMACH_AC97_PCMIN,
DMACH_AC97_PCMOUT,
DMACH_MIPI_HSI4,
DMACH_MIPI_HSI5,
};
struct dma_pl330_platdata exynos4_pdma0_pdata;
static AMBA_AHB_DEVICE(exynos4_pdma0, "dma-pl330.0", 0x00041330,
EXYNOS4_PA_PDMA0, {IRQ_PDMA0}, &exynos4_pdma0_pdata);
static u8 pdma1_peri[] = {
static u8 exynos4210_pdma1_peri[] = {
DMACH_PCM0_RX,
DMACH_PCM0_TX,
DMACH_PCM1_RX,
@ -105,19 +138,84 @@ static u8 pdma1_peri[] = {
DMACH_SLIMBUS5_TX,
};
static struct dma_pl330_platdata exynos4_pdma1_pdata = {
.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
.peri_id = pdma1_peri,
static u8 exynos4212_pdma1_peri[] = {
DMACH_PCM0_RX,
DMACH_PCM0_TX,
DMACH_PCM1_RX,
DMACH_PCM1_TX,
DMACH_MIPI_HSI2,
DMACH_MIPI_HSI3,
DMACH_SPI1_RX,
DMACH_SPI1_TX,
DMACH_I2S0S_TX,
DMACH_I2S0_RX,
DMACH_I2S0_TX,
DMACH_I2S1_RX,
DMACH_I2S1_TX,
DMACH_UART0_RX,
DMACH_UART0_TX,
DMACH_UART1_RX,
DMACH_UART1_TX,
DMACH_UART3_RX,
DMACH_UART3_TX,
DMACH_SLIMBUS1_RX,
DMACH_SLIMBUS1_TX,
DMACH_SLIMBUS3_RX,
DMACH_SLIMBUS3_TX,
DMACH_SLIMBUS5_RX,
DMACH_SLIMBUS5_TX,
DMACH_SLIMBUS0AUX_RX,
DMACH_SLIMBUS0AUX_TX,
DMACH_SPDIF,
DMACH_MIPI_HSI6,
DMACH_MIPI_HSI7,
};
static struct dma_pl330_platdata exynos4_pdma1_pdata;
static AMBA_AHB_DEVICE(exynos4_pdma1, "dma-pl330.1", 0x00041330,
EXYNOS4_PA_PDMA1, {IRQ_PDMA1}, &exynos4_pdma1_pdata);
static u8 mdma_peri[] = {
DMACH_MTOM_0,
DMACH_MTOM_1,
DMACH_MTOM_2,
DMACH_MTOM_3,
DMACH_MTOM_4,
DMACH_MTOM_5,
DMACH_MTOM_6,
DMACH_MTOM_7,
};
static struct dma_pl330_platdata exynos4_mdma1_pdata = {
.nr_valid_peri = ARRAY_SIZE(mdma_peri),
.peri_id = mdma_peri,
};
static AMBA_AHB_DEVICE(exynos4_mdma1, "dma-pl330.2", 0x00041330,
EXYNOS4_PA_MDMA1, {IRQ_MDMA1}, &exynos4_mdma1_pdata);
static int __init exynos4_dma_init(void)
{
if (of_have_populated_dt())
return 0;
if (soc_is_exynos4210()) {
exynos4_pdma0_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4210_pdma0_peri);
exynos4_pdma0_pdata.peri_id = exynos4210_pdma0_peri;
exynos4_pdma1_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4210_pdma1_peri);
exynos4_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
exynos4_pdma0_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4212_pdma0_peri);
exynos4_pdma0_pdata.peri_id = exynos4212_pdma0_peri;
exynos4_pdma1_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4212_pdma1_peri);
exynos4_pdma1_pdata.peri_id = exynos4212_pdma1_peri;
}
dma_cap_set(DMA_SLAVE, exynos4_pdma0_pdata.cap_mask);
dma_cap_set(DMA_CYCLIC, exynos4_pdma0_pdata.cap_mask);
amba_device_register(&exynos4_pdma0_device, &iomem_resource);
@ -126,6 +224,9 @@ static int __init exynos4_dma_init(void)
dma_cap_set(DMA_CYCLIC, exynos4_pdma1_pdata.cap_mask);
amba_device_register(&exynos4_pdma1_device, &iomem_resource);
dma_cap_set(DMA_MEMCPY, exynos4_mdma1_pdata.cap_mask);
amba_device_register(&exynos4_mdma1_device, &iomem_resource);
return 0;
}
arch_initcall(exynos4_dma_init);

View File

@ -43,6 +43,8 @@
#define IRQ_EINT15 IRQ_SPI(31)
#define IRQ_EINT16_31 IRQ_SPI(32)
#define IRQ_MDMA0 IRQ_SPI(33)
#define IRQ_MDMA1 IRQ_SPI(34)
#define IRQ_PDMA0 IRQ_SPI(35)
#define IRQ_PDMA1 IRQ_SPI(36)
#define IRQ_TIMER0_VIC IRQ_SPI(37)

View File

@ -72,7 +72,8 @@
#define EXYNOS4_PA_TWD 0x10500600
#define EXYNOS4_PA_L2CC 0x10502000
#define EXYNOS4_PA_MDMA 0x10810000
#define EXYNOS4_PA_MDMA0 0x10810000
#define EXYNOS4_PA_MDMA1 0x12840000
#define EXYNOS4_PA_PDMA0 0x12680000
#define EXYNOS4_PA_PDMA1 0x12690000

View File

@ -117,7 +117,7 @@ static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
};
static struct regulator_consumer_supply emmc_supplies[] = {
REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
REGULATOR_SUPPLY("vmmc", "exynos4-sdhci.0"),
REGULATOR_SUPPLY("vmmc", "dw_mmc"),
};
@ -418,7 +418,7 @@ static struct regulator_consumer_supply __initdata max8997_ldo12_[] = {
REGULATOR_SUPPLY("vddio", "6-003c"), /* HDC802 */
};
static struct regulator_consumer_supply __initdata max8997_ldo13_[] = {
REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), /* TFLASH */
REGULATOR_SUPPLY("vmmc", "exynos4-sdhci.2"), /* TFLASH */
};
static struct regulator_consumer_supply __initdata max8997_ldo14_[] = {
REGULATOR_SUPPLY("inmotor", "max8997-haptic"),

View File

@ -752,7 +752,7 @@ static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
};
static struct regulator_consumer_supply mmc0_supplies[] = {
REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
REGULATOR_SUPPLY("vmmc", "exynos4-sdhci.0"),
};
static struct regulator_init_data mmc0_fixed_voltage_init_data = {

View File

@ -298,6 +298,7 @@ config MACH_MX27_3DS
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_KEYPAD
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_MX2_CAMERA
select IMX_HAVE_PLATFORM_MXC_EHCI
select IMX_HAVE_PLATFORM_MXC_MMC
select IMX_HAVE_PLATFORM_SPI_IMX

View File

@ -329,6 +329,12 @@
#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
#define BP_CCOSR_CKO1_EN 7
#define BP_CCOSR_CKO1_PODF 4
#define BM_CCOSR_CKO1_PODF (0x7 << 4)
#define BP_CCOSR_CKO1_SEL 0
#define BM_CCOSR_CKO1_SEL (0xf << 0)
#define FREQ_480M 480000000
#define FREQ_528M 528000000
#define FREQ_594M 594000000
@ -393,6 +399,7 @@ static struct clk ipu1_di1_clk;
static struct clk ipu2_di0_clk;
static struct clk ipu2_di1_clk;
static struct clk enfc_clk;
static struct clk cko1_clk;
static struct clk dummy_clk = {};
static unsigned long external_high_reference;
@ -938,6 +945,24 @@ static void _clk_disable(struct clk *clk)
writel_relaxed(reg, clk->enable_reg);
}
static int _clk_enable_1b(struct clk *clk)
{
u32 reg;
reg = readl_relaxed(clk->enable_reg);
reg |= 0x1 << clk->enable_shift;
writel_relaxed(reg, clk->enable_reg);
return 0;
}
static void _clk_disable_1b(struct clk *clk)
{
u32 reg;
reg = readl_relaxed(clk->enable_reg);
reg &= ~(0x1 << clk->enable_shift);
writel_relaxed(reg, clk->enable_reg);
}
struct divider {
struct clk *clk;
void __iomem *reg;
@ -983,6 +1008,7 @@ DEF_CLK_DIV1(ipu2_di0_pre_div, &ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE);
DEF_CLK_DIV1(ipu2_di1_pre_div, &ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE);
DEF_CLK_DIV1(ipu1_div, &ipu1_clk, CSCDR3, IPU1_HSP);
DEF_CLK_DIV1(ipu2_div, &ipu2_clk, CSCDR3, IPU2_HSP);
DEF_CLK_DIV1(cko1_div, &cko1_clk, CCOSR, CKO1);
#define DEF_CLK_DIV2(d, c, r, b) \
static struct divider d = { \
@ -1038,6 +1064,7 @@ static struct divider *dividers[] = {
&enfc_div,
&spdif_div,
&asrc_serial_div,
&cko1_div,
};
static unsigned long ldb_di_clk_get_rate(struct clk *clk)
@ -1625,6 +1652,32 @@ DEF_IPU_DI_MUX(CSCDR2, 2, 1);
DEF_IPU_MUX(1);
DEF_IPU_MUX(2);
static struct multiplexer cko1_mux = {
.clk = &cko1_clk,
.reg = CCOSR,
.bp = BP_CCOSR_CKO1_SEL,
.bm = BM_CCOSR_CKO1_SEL,
.parents = {
&pll3_usb_otg,
&pll2_bus,
&pll1_sys,
&pll5_video,
&dummy_clk,
&axi_clk,
&enfc_clk,
&ipu1_di0_clk,
&ipu1_di1_clk,
&ipu2_di0_clk,
&ipu2_di1_clk,
&ahb_clk,
&ipg_clk,
&ipg_perclk,
&ckil_clk,
&pll4_audio,
NULL
},
};
static struct multiplexer *multiplexers[] = {
&axi_mux,
&periph_mux,
@ -1667,6 +1720,7 @@ static struct multiplexer *multiplexers[] = {
&ipu2_di1_mux,
&ipu1_mux,
&ipu2_mux,
&cko1_mux,
};
static int _clk_set_parent(struct clk *clk, struct clk *parent)
@ -1690,7 +1744,7 @@ static int _clk_set_parent(struct clk *clk, struct clk *parent)
break;
i++;
}
if (!m->parents[i])
if (!m->parents[i] || m->parents[i] == &dummy_clk)
return -EINVAL;
val = readl_relaxed(m->reg);
@ -1745,6 +1799,20 @@ DEF_NG_CLK(asrc_serial_clk, &pll3_usb_otg);
.secondary = s, \
}
#define DEF_CLK_1B(name, er, es, p, s) \
static struct clk name = { \
.enable_reg = er, \
.enable_shift = es, \
.enable = _clk_enable_1b, \
.disable = _clk_disable_1b, \
.get_rate = _clk_get_rate, \
.set_rate = _clk_set_rate, \
.round_rate = _clk_round_rate, \
.set_parent = _clk_set_parent, \
.parent = p, \
.secondary = s, \
}
DEF_CLK(aips_tz1_clk, CCGR0, CG0, &ahb_clk, NULL);
DEF_CLK(aips_tz2_clk, CCGR0, CG1, &ahb_clk, NULL);
DEF_CLK(apbh_dma_clk, CCGR0, CG2, &ahb_clk, NULL);
@ -1811,6 +1879,7 @@ DEF_CLK(usdhc4_clk, CCGR6, CG4, &pll2_pfd_400m, NULL);
DEF_CLK(emi_slow_clk, CCGR6, CG5, &axi_clk, NULL);
DEF_CLK(vdo_axi_clk, CCGR6, CG6, &axi_clk, NULL);
DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, NULL);
DEF_CLK_1B(cko1_clk, CCOSR, BP_CCOSR_CKO1_EN, &pll2_bus, NULL);
static int pcie_clk_enable(struct clk *clk)
{
@ -1922,6 +1991,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
_REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
_REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
_REGISTER_CLOCK(NULL, "cko1_clk", cko1_clk),
};
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
@ -2029,6 +2099,8 @@ int __init mx6q_clocks_init(void)
clk_set_rate(&usdhc3_clk, 49500000);
clk_set_rate(&usdhc4_clk, 49500000);
clk_set_parent(&cko1_clk, &ahb_clk);
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
base = of_iomap(np, 0);
WARN_ON(!base);

View File

@ -17,7 +17,7 @@
#include <mach/hardware.h>
static struct map_desc imx_lluart_desc = {
#ifdef CONFIG_DEBUG_IMX6Q_UART
#ifdef CONFIG_DEBUG_IMX6Q_UART4
.virtual = MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
.pfn = __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
.length = MX6Q_UART4_SIZE,

View File

@ -37,8 +37,8 @@
#define MX21ADS_REG_ADDR(offset) (void __force __iomem *) \
(MX21ADS_MMIO_BASE_ADDR + (offset))
#define MX21ADS_CS8900A_MMIO_SIZE 0x200000
#define MX21ADS_CS8900A_IRQ IRQ_GPIOE(11)
#define MX21ADS_CS8900A_IOBASE_REG MX21ADS_REG_ADDR(0x000000)
#define MX21ADS_ST16C255_IOBASE_REG MX21ADS_REG_ADDR(0x200000)
#define MX21ADS_VERSION_REG MX21ADS_REG_ADDR(0x400000)
#define MX21ADS_IO_REG MX21ADS_REG_ADDR(0x800000)
@ -159,6 +159,18 @@ static struct platform_device mx21ads_nor_mtd_device = {
.resource = &mx21ads_flash_resource,
};
static const struct resource mx21ads_cs8900_resources[] __initconst = {
DEFINE_RES_MEM(MX21_CS1_BASE_ADDR, MX21ADS_CS8900A_MMIO_SIZE),
DEFINE_RES_IRQ(MX21ADS_CS8900A_IRQ),
};
static const struct platform_device_info mx21ads_cs8900_devinfo __initconst = {
.name = "cs89x0",
.id = 0,
.res = mx21ads_cs8900_resources,
.num_res = ARRAY_SIZE(mx21ads_cs8900_resources),
};
static const struct imxuart_platform_data uart_pdata_rts __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@ -292,6 +304,8 @@ static void __init mx21ads_board_init(void)
imx21_add_mxc_nand(&mx21ads_nand_board_info);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
platform_device_register_full(
(struct platform_device_info *)&mx21ads_cs8900_devinfo);
}
static void __init mx21ads_timer_init(void)

View File

@ -31,6 +31,8 @@
#include <linux/regulator/machine.h>
#include <linux/spi/l4f00242t03.h>
#include <media/soc_camera.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
@ -52,6 +54,8 @@
#define SD1_CD IMX_GPIO_NR(2, 26)
#define LCD_RESET IMX_GPIO_NR(1, 3)
#define LCD_ENABLE IMX_GPIO_NR(1, 31)
#define CSI_PWRDWN IMX_GPIO_NR(4, 19)
#define CSI_RESET IMX_GPIO_NR(3, 6)
static const int mx27pdk_pins[] __initconst = {
/* UART1 */
@ -141,6 +145,26 @@ static const int mx27pdk_pins[] __initconst = {
PA30_PF_CONTRAST,
LCD_ENABLE | GPIO_GPIO | GPIO_OUT,
LCD_RESET | GPIO_GPIO | GPIO_OUT,
/* CSI */
PB10_PF_CSI_D0,
PB11_PF_CSI_D1,
PB12_PF_CSI_D2,
PB13_PF_CSI_D3,
PB14_PF_CSI_D4,
PB15_PF_CSI_MCLK,
PB16_PF_CSI_PIXCLK,
PB17_PF_CSI_D5,
PB18_PF_CSI_D6,
PB19_PF_CSI_D7,
PB20_PF_CSI_VSYNC,
PB21_PF_CSI_HSYNC,
CSI_PWRDWN | GPIO_GPIO | GPIO_OUT,
CSI_RESET | GPIO_GPIO | GPIO_OUT,
};
static struct gpio mx27_3ds_camera_gpios[] = {
{ CSI_PWRDWN, GPIOF_OUT_INIT_HIGH, "camera-power" },
{ CSI_RESET, GPIOF_OUT_INIT_HIGH, "camera-reset" },
};
static const struct imxuart_platform_data uart_pdata __initconst = {
@ -242,6 +266,7 @@ static struct regulator_init_data gpo_init = {
static struct regulator_consumer_supply vmmc1_consumers[] = {
REGULATOR_SUPPLY("vcore", "spi0.0"),
REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
};
static struct regulator_init_data vmmc1_init = {
@ -270,6 +295,22 @@ static struct regulator_init_data vgen_init = {
.consumer_supplies = vgen_consumers,
};
static struct regulator_consumer_supply vvib_consumers[] = {
REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
};
static struct regulator_init_data vvib_init = {
.constraints = {
.min_uV = 1300000,
.max_uV = 1300000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(vvib_consumers),
.consumer_supplies = vvib_consumers,
};
static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
{
.id = MC13783_REG_VMMC1,
@ -283,6 +324,9 @@ static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
}, {
.id = MC13783_REG_GPO3, /* Turn on 3.3V */
.init_data = &gpo_init,
}, {
.id = MC13783_REG_VVIB, /* Power OV2640 */
.init_data = &vvib_init,
},
};
@ -311,6 +355,51 @@ static const struct spi_imx_master spi2_pdata __initconst = {
.num_chipselect = ARRAY_SIZE(spi2_chipselect),
};
static int mx27_3ds_camera_power(struct device *dev, int on)
{
/* enable or disable the camera */
pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
gpio_set_value(CSI_PWRDWN, on ? 0 : 1);
if (!on)
goto out;
/* If enabled, give a reset impulse */
gpio_set_value(CSI_RESET, 0);
msleep(20);
gpio_set_value(CSI_RESET, 1);
msleep(100);
out:
return 0;
}
static struct i2c_board_info mx27_3ds_i2c_camera = {
I2C_BOARD_INFO("ov2640", 0x30),
};
static struct regulator_bulk_data mx27_3ds_camera_regs[] = {
{ .supply = "cmos_vcore" },
{ .supply = "cmos_2v8" },
};
static struct soc_camera_link iclink_ov2640 = {
.bus_id = 0,
.board_info = &mx27_3ds_i2c_camera,
.i2c_adapter_id = 0,
.power = mx27_3ds_camera_power,
.regulators = mx27_3ds_camera_regs,
.num_regulators = ARRAY_SIZE(mx27_3ds_camera_regs),
};
static struct platform_device mx27_3ds_ov2640 = {
.name = "soc-camera-pdrv",
.id = 0,
.dev = {
.platform_data = &iclink_ov2640,
},
};
static struct imx_fb_videomode mx27_3ds_modes[] = {
{ /* 480x640 @ 60 Hz */
.mode = {
@ -367,12 +456,21 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
},
};
static struct platform_device *devices[] __initdata = {
&mx27_3ds_ov2640,
};
static const struct mx2_camera_platform_data mx27_3ds_cam_pdata __initconst = {
.clk = 26000000,
};
static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
.bitrate = 100000,
};
static void __init mx27pdk_init(void)
{
int ret;
imx27_soc_init();
mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
@ -404,7 +502,17 @@ static void __init mx27pdk_init(void)
if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT))
pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
platform_add_devices(devices, ARRAY_SIZE(devices));
imx27_add_imx_fb(&mx27_3ds_fb_data);
ret = gpio_request_array(mx27_3ds_camera_gpios,
ARRAY_SIZE(mx27_3ds_camera_gpios));
if (ret) {
pr_err("Failed to request camera gpios");
iclink_ov2640.power = NULL;
}
imx27_add_mx2_camera(&mx27_3ds_cam_pdata);
}
static void __init mx27pdk_timer_init(void)

View File

@ -28,7 +28,6 @@
#include <asm/memory.h>
#include <asm/mach/map.h>
#include <mach/common.h>
#include <mach/board-mx31ads.h>
#include <mach/iomux-mx3.h>
#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
@ -39,6 +38,9 @@
#include "devices-imx31.h"
/* Base address of PBC controller */
#define PBC_BASE_ADDRESS MX31_CS4_BASE_ADDR_VIRT
/* PBC Board interrupt status register */
#define PBC_INTSTATUS 0x000016
@ -62,6 +64,7 @@
#define PBC_INTMASK_CLEAR_REG (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS)
#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_4)
#define MXC_EXP_IO_BASE MXC_BOARD_IRQ_START
#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE)
#define EXPIO_INT_XUART_INTA (MXC_EXP_IO_BASE + 10)
@ -69,6 +72,10 @@
#define MXC_MAX_EXP_IO_LINES 16
/* CS8900 */
#define EXPIO_INT_ENET_INT (MXC_EXP_IO_BASE + 8)
#define CS4_CS8900_MMIO_START 0x20000
/*
* The serial port definition structure.
*/
@ -101,11 +108,29 @@ static struct platform_device serial_device = {
},
};
static const struct resource mx31ads_cs8900_resources[] __initconst = {
DEFINE_RES_MEM(MX31_CS4_BASE_ADDR + CS4_CS8900_MMIO_START, SZ_64K),
DEFINE_RES_IRQ(EXPIO_INT_ENET_INT),
};
static const struct platform_device_info mx31ads_cs8900_devinfo __initconst = {
.name = "cs89x0",
.id = 0,
.res = mx31ads_cs8900_resources,
.num_res = ARRAY_SIZE(mx31ads_cs8900_resources),
};
static int __init mxc_init_extuart(void)
{
return platform_device_register(&serial_device);
}
static void __init mxc_init_ext_ethernet(void)
{
platform_device_register_full(
(struct platform_device_info *)&mx31ads_cs8900_devinfo);
}
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@ -492,12 +517,15 @@ static void __init mxc_init_audio(void)
mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
}
/* static mappings */
/*
* Static mappings, starting from the CS4 start address up to the start address
* of the CS8900.
*/
static struct map_desc mx31ads_io_desc[] __initdata = {
{
.virtual = MX31_CS4_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(MX31_CS4_BASE_ADDR),
.length = MX31_CS4_SIZE / 2,
.length = CS4_CS8900_MMIO_START,
.type = MT_DEVICE
},
};
@ -522,6 +550,7 @@ static void __init mx31ads_init(void)
mxc_init_imx_uart();
mxc_init_i2c();
mxc_init_audio();
mxc_init_ext_ethernet();
}
static void __init mx31ads_timer_init(void)

View File

@ -507,7 +507,7 @@ static void mx31moboard_poweroff(void)
struct clk *clk = clk_get_sys("imx2-wdt.0", NULL);
if (!IS_ERR(clk))
clk_enable(clk);
clk_prepare_enable(clk);
mxc_iomux_mode(MX31_PIN_WATCHDOG_RST__WATCHDOG_RST);

View File

@ -89,7 +89,7 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
static int mx5_suspend_prepare(void)
{
return clk_enable(gpc_dvfs_clk);
return clk_prepare_enable(gpc_dvfs_clk);
}
static int mx5_suspend_enter(suspend_state_t state)
@ -119,7 +119,7 @@ static int mx5_suspend_enter(suspend_state_t state)
static void mx5_suspend_finish(void)
{
clk_disable(gpc_dvfs_clk);
clk_disable_unprepare(gpc_dvfs_clk);
}
static int mx5_pm_valid(suspend_state_t state)

View File

@ -721,6 +721,41 @@ static struct clk clk_tsc = {
.get_rate = local_return_parent_rate,
};
static int adc_onoff_enable(struct clk *clk, int enable)
{
u32 tmp;
u32 divider;
/* Use PERIPH_CLOCK */
tmp = __raw_readl(LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
tmp |= LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL;
/*
* Set clock divider so that we have equal to or less than
* 4.5MHz clock at ADC
*/
divider = clk->get_rate(clk) / 4500000 + 1;
tmp |= divider;
__raw_writel(tmp, LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
/* synchronize rate of this clock w/ actual HW setting */
clk->rate = clk->get_rate(clk->parent) / divider;
if (enable == 0)
__raw_writel(0, clk->enable_reg);
else
__raw_writel(clk->enable_mask, clk->enable_reg);
return 0;
}
static struct clk clk_adc = {
.parent = &clk_pclk,
.enable = adc_onoff_enable,
.enable_reg = LPC32XX_CLKPWR_ADC_CLK_CTRL,
.enable_mask = LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN,
.get_rate = local_return_parent_rate,
};
static int mmc_onoff_enable(struct clk *clk, int enable)
{
u32 tmp;
@ -1055,6 +1090,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1)
_REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan)
_REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand)
_REGISTER_CLOCK("lpc32xx-adc", NULL, clk_adc)
_REGISTER_CLOCK(NULL, "i2s0_ck", clk_i2s0)
_REGISTER_CLOCK(NULL, "i2s1_ck", clk_i2s1)
_REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc)

View File

@ -137,6 +137,28 @@ struct platform_device lpc32xx_rtc_device = {
.resource = lpc32xx_rtc_resources,
};
/*
* ADC support
*/
static struct resource adc_resources[] = {
{
.start = LPC32XX_ADC_BASE,
.end = LPC32XX_ADC_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
}, {
.start = IRQ_LPC32XX_TS_IRQ,
.end = IRQ_LPC32XX_TS_IRQ,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device lpc32xx_adc_device = {
.name = "lpc32xx-adc",
.id = -1,
.num_resources = ARRAY_SIZE(adc_resources),
.resource = adc_resources,
};
/*
* Returns the unique ID for the device
*/

View File

@ -29,6 +29,7 @@ extern struct platform_device lpc32xx_i2c0_device;
extern struct platform_device lpc32xx_i2c1_device;
extern struct platform_device lpc32xx_i2c2_device;
extern struct platform_device lpc32xx_tsc_device;
extern struct platform_device lpc32xx_adc_device;
extern struct platform_device lpc32xx_rtc_device;
/*

View File

@ -254,6 +254,7 @@ static struct platform_device *phy3250_devs[] __initdata = {
&lpc32xx_i2c2_device,
&lpc32xx_watchdog_device,
&lpc32xx_gpio_led_device,
&lpc32xx_adc_device,
};
static struct amba_device *amba_devs[] __initdata = {

View File

@ -22,6 +22,7 @@ extern struct pxa_device_desc pxa910_device_pwm4;
extern struct pxa_device_desc pxa910_device_nand;
extern struct platform_device pxa910_device_gpio;
extern struct platform_device pxa910_device_rtc;
static inline int pxa910_add_uart(int id)
{

View File

@ -57,6 +57,7 @@
#define APBC_PXA910_SSP1 APBC_REG(0x01c)
#define APBC_PXA910_SSP2 APBC_REG(0x020)
#define APBC_PXA910_IPC APBC_REG(0x024)
#define APBC_PXA910_RTC APBC_REG(0x028)
#define APBC_PXA910_TWSI0 APBC_REG(0x02c)
#define APBC_PXA910_KPC APBC_REG(0x030)
#define APBC_PXA910_TIMERS APBC_REG(0x034)

View File

@ -0,0 +1,23 @@
#ifndef __ASM_MACH_REGS_RTC_H
#define __ASM_MACH_REGS_RTC_H
#include <mach/addr-map.h>
#define RTC_VIRT_BASE (APB_VIRT_BASE + 0x10000)
#define RTC_REG(x) (*((volatile u32 __iomem *)(RTC_VIRT_BASE + (x))))
/*
* Real Time Clock
*/
#define RCNR RTC_REG(0x00) /* RTC Count Register */
#define RTAR RTC_REG(0x04) /* RTC Alarm Register */
#define RTSR RTC_REG(0x08) /* RTC Status Register */
#define RTTR RTC_REG(0x0C) /* RTC Timer Trim Register */
#define RTSR_HZE (1 << 3) /* HZ interrupt enable */
#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */
#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */
#define RTSR_AL (1 << 0) /* RTC alarm detected */
#endif /* __ASM_MACH_REGS_RTC_H */

View File

@ -92,6 +92,7 @@ static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
static APBC_CLK(gpio, PXA910_GPIO, 0, 13000000);
static APBC_CLK(rtc, PXA910_RTC, 8, 32768);
static APMU_CLK(nand, NAND, 0x19b, 156000000);
static APMU_CLK(u2o, USB, 0x1b, 480000000);
@ -109,6 +110,7 @@ static struct clk_lookup pxa910_clkregs[] = {
INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
INIT_CLKREG(&clk_u2o, "pxa-u2o", "U2OCLK"),
INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL),
};
static int __init pxa910_init(void)
@ -184,3 +186,28 @@ struct platform_device pxa910_device_gpio = {
.num_resources = ARRAY_SIZE(pxa910_resource_gpio),
.resource = pxa910_resource_gpio,
};
static struct resource pxa910_resource_rtc[] = {
{
.start = 0xd4010000,
.end = 0xd401003f,
.flags = IORESOURCE_MEM,
}, {
.start = IRQ_PXA910_RTC_INT,
.end = IRQ_PXA910_RTC_INT,
.name = "rtc 1Hz",
.flags = IORESOURCE_IRQ,
}, {
.start = IRQ_PXA910_RTC_ALARM,
.end = IRQ_PXA910_RTC_ALARM,
.name = "rtc alarm",
.flags = IORESOURCE_IRQ,
},
};
struct platform_device pxa910_device_rtc = {
.name = "sa1100-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(pxa910_resource_rtc),
.resource = pxa910_resource_rtc,
};

View File

@ -124,6 +124,7 @@ static struct platform_device ttc_dkb_device_onenand = {
static struct platform_device *ttc_dkb_devices[] = {
&pxa910_device_gpio,
&pxa910_device_rtc,
&ttc_dkb_device_onenand,
};

View File

@ -439,6 +439,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
_REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
_REGISTER_CLOCK("imx23-gpmi-nand", NULL, gpmi_clk)
};
static int clk_misc_init(void)

View File

@ -617,6 +617,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("duart", NULL, uart_clk)
_REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk)
_REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk)
_REGISTER_CLOCK("imx28-gpmi-nand", NULL, gpmi_clk)
_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
_REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
_REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)

View File

@ -21,6 +21,10 @@ extern const struct mxs_auart_data mx23_auart_data[] __initconst;
#define mx23_add_auart0() mx23_add_auart(0)
#define mx23_add_auart1() mx23_add_auart(1)
extern const struct mxs_gpmi_nand_data mx23_gpmi_nand_data __initconst;
#define mx23_add_gpmi_nand(pdata) \
mxs_add_gpmi_nand(pdata, &mx23_gpmi_nand_data)
extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
#define mx23_add_mxs_mmc(id, pdata) \
mxs_add_mxs_mmc(&mx23_mxs_mmc_data[id], pdata)

View File

@ -34,6 +34,10 @@ extern const struct mxs_flexcan_data mx28_flexcan_data[] __initconst;
#define mx28_add_flexcan0(pdata) mx28_add_flexcan(0, pdata)
#define mx28_add_flexcan1(pdata) mx28_add_flexcan(1, pdata)
extern const struct mxs_gpmi_nand_data mx28_gpmi_nand_data __initconst;
#define mx28_add_gpmi_nand(pdata) \
mxs_add_gpmi_nand(pdata, &mx28_gpmi_nand_data)
extern const struct mxs_mxs_i2c_data mx28_mxs_i2c_data[] __initconst;
#define mx28_add_mxs_i2c(id) mxs_add_mxs_i2c(&mx28_mxs_i2c_data[id])

View File

@ -12,6 +12,9 @@ config MXS_HAVE_PLATFORM_FLEXCAN
select HAVE_CAN_FLEXCAN if CAN
bool
config MXS_HAVE_PLATFORM_GPMI_NAND
bool
config MXS_HAVE_PLATFORM_MXS_I2C
bool

View File

@ -3,6 +3,7 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
obj-y += platform-dma.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_GPMI_NAND) += platform-gpmi-nand.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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.
*/
#include <asm/sizes.h>
#include <mach/mx23.h>
#include <mach/mx28.h>
#include <mach/devices-common.h>
#include <linux/dma-mapping.h>
#ifdef CONFIG_SOC_IMX23
const struct mxs_gpmi_nand_data mx23_gpmi_nand_data __initconst = {
.devid = "imx23-gpmi-nand",
.res = {
/* GPMI */
DEFINE_RES_MEM_NAMED(MX23_GPMI_BASE_ADDR, SZ_8K,
GPMI_NAND_GPMI_REGS_ADDR_RES_NAME),
DEFINE_RES_IRQ_NAMED(MX23_INT_GPMI_ATTENTION,
GPMI_NAND_GPMI_INTERRUPT_RES_NAME),
/* BCH */
DEFINE_RES_MEM_NAMED(MX23_BCH_BASE_ADDR, SZ_8K,
GPMI_NAND_BCH_REGS_ADDR_RES_NAME),
DEFINE_RES_IRQ_NAMED(MX23_INT_BCH,
GPMI_NAND_BCH_INTERRUPT_RES_NAME),
/* DMA */
DEFINE_RES_NAMED(MX23_DMA_GPMI0,
MX23_DMA_GPMI3 - MX23_DMA_GPMI0 + 1,
GPMI_NAND_DMA_CHANNELS_RES_NAME,
IORESOURCE_DMA),
DEFINE_RES_IRQ_NAMED(MX23_INT_GPMI_DMA,
GPMI_NAND_DMA_INTERRUPT_RES_NAME),
},
};
#endif
#ifdef CONFIG_SOC_IMX28
const struct mxs_gpmi_nand_data mx28_gpmi_nand_data __initconst = {
.devid = "imx28-gpmi-nand",
.res = {
/* GPMI */
DEFINE_RES_MEM_NAMED(MX28_GPMI_BASE_ADDR, SZ_8K,
GPMI_NAND_GPMI_REGS_ADDR_RES_NAME),
DEFINE_RES_IRQ_NAMED(MX28_INT_GPMI,
GPMI_NAND_GPMI_INTERRUPT_RES_NAME),
/* BCH */
DEFINE_RES_MEM_NAMED(MX28_BCH_BASE_ADDR, SZ_8K,
GPMI_NAND_BCH_REGS_ADDR_RES_NAME),
DEFINE_RES_IRQ_NAMED(MX28_INT_BCH,
GPMI_NAND_BCH_INTERRUPT_RES_NAME),
/* DMA */
DEFINE_RES_NAMED(MX28_DMA_GPMI0,
MX28_DMA_GPMI7 - MX28_DMA_GPMI0 + 1,
GPMI_NAND_DMA_CHANNELS_RES_NAME,
IORESOURCE_DMA),
DEFINE_RES_IRQ_NAMED(MX28_INT_GPMI_DMA,
GPMI_NAND_DMA_INTERRUPT_RES_NAME),
},
};
#endif
struct platform_device *__init
mxs_add_gpmi_nand(const struct gpmi_nand_platform_data *pdata,
const struct mxs_gpmi_nand_data *data)
{
return mxs_add_platform_device_dmamask(data->devid, -1,
data->res, GPMI_NAND_RES_SIZE,
pdata, sizeof(*pdata), DMA_BIT_MASK(32));
}

View File

@ -66,6 +66,16 @@ struct platform_device *__init mxs_add_flexcan(
const struct mxs_flexcan_data *data,
const struct flexcan_platform_data *pdata);
/* gpmi-nand */
#include <linux/mtd/gpmi-nand.h>
struct mxs_gpmi_nand_data {
const char *devid;
const struct resource res[GPMI_NAND_RES_SIZE];
};
struct platform_device *__init
mxs_add_gpmi_nand(const struct gpmi_nand_platform_data *pdata,
const struct mxs_gpmi_nand_data *data);
/* i2c */
struct mxs_mxs_i2c_data {
int id;

View File

@ -29,6 +29,7 @@
#include "omap_hwmod_common_data.h"
#include "smartreflex.h"
#include "prm-regbits-34xx.h"
#include "cm-regbits-34xx.h"
#include "wd_timer.h"
@ -376,6 +377,16 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
{ .irq = 18},
{ .irq = -1 }
};
static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
{ .irq = 19},
{ .irq = -1 }
};
/* L4 CORE -> SR1 interface */
static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
{
@ -2664,6 +2675,10 @@ static struct omap_hwmod_class omap36xx_smartreflex_hwmod_class = {
};
/* SR1 */
static struct omap_smartreflex_dev_attr sr1_dev_attr = {
.sensor_voltdm_name = "mpu_iva",
};
static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
&omap3_l4_core__sr1,
};
@ -2672,7 +2687,6 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
.name = "sr1_hwmod",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
.vdd_name = "mpu_iva",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@ -2684,6 +2698,8 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
},
.slaves = omap3_sr1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
.dev_attr = &sr1_dev_attr,
.mpu_irqs = omap3_smartreflex_mpu_irqs,
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
@ -2691,7 +2707,6 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
.name = "sr1_hwmod",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
.vdd_name = "mpu_iva",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@ -2703,9 +2718,15 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
},
.slaves = omap3_sr1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
.dev_attr = &sr1_dev_attr,
.mpu_irqs = omap3_smartreflex_mpu_irqs,
};
/* SR2 */
static struct omap_smartreflex_dev_attr sr2_dev_attr = {
.sensor_voltdm_name = "core",
};
static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
&omap3_l4_core__sr2,
};
@ -2714,7 +2735,6 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
.name = "sr2_hwmod",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr2_fck",
.vdd_name = "core",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@ -2726,6 +2746,8 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
},
.slaves = omap3_sr2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
.dev_attr = &sr2_dev_attr,
.mpu_irqs = omap3_smartreflex_core_irqs,
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
@ -2733,7 +2755,6 @@ static struct omap_hwmod omap36xx_sr2_hwmod = {
.name = "sr2_hwmod",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr2_fck",
.vdd_name = "core",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@ -2745,6 +2766,8 @@ static struct omap_hwmod omap36xx_sr2_hwmod = {
},
.slaves = omap3_sr2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
.dev_attr = &sr2_dev_attr,
.mpu_irqs = omap3_smartreflex_core_irqs,
};
/*

View File

@ -33,6 +33,7 @@
#include "omap_hwmod_common_data.h"
#include "smartreflex.h"
#include "cm1_44xx.h"
#include "cm2_44xx.h"
#include "prm44xx.h"
@ -3962,6 +3963,10 @@ static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = {
};
/* smartreflex_core */
static struct omap_smartreflex_dev_attr smartreflex_core_dev_attr = {
.sensor_voltdm_name = "core",
};
static struct omap_hwmod omap44xx_smartreflex_core_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = {
{ .irq = 19 + OMAP44XX_IRQ_GIC_START },
@ -3998,7 +4003,6 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
.mpu_irqs = omap44xx_smartreflex_core_irqs,
.main_clk = "smartreflex_core_fck",
.vdd_name = "core",
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET,
@ -4008,9 +4012,14 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
},
.slaves = omap44xx_smartreflex_core_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
.dev_attr = &smartreflex_core_dev_attr,
};
/* smartreflex_iva */
static struct omap_smartreflex_dev_attr smartreflex_iva_dev_attr = {
.sensor_voltdm_name = "iva",
};
static struct omap_hwmod omap44xx_smartreflex_iva_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = {
{ .irq = 102 + OMAP44XX_IRQ_GIC_START },
@ -4046,7 +4055,6 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
.clkdm_name = "l4_ao_clkdm",
.mpu_irqs = omap44xx_smartreflex_iva_irqs,
.main_clk = "smartreflex_iva_fck",
.vdd_name = "iva",
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET,
@ -4056,9 +4064,14 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
},
.slaves = omap44xx_smartreflex_iva_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
.dev_attr = &smartreflex_iva_dev_attr,
};
/* smartreflex_mpu */
static struct omap_smartreflex_dev_attr smartreflex_mpu_dev_attr = {
.sensor_voltdm_name = "mpu",
};
static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod;
static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = {
{ .irq = 18 + OMAP44XX_IRQ_GIC_START },
@ -4094,7 +4107,6 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
.clkdm_name = "l4_ao_clkdm",
.mpu_irqs = omap44xx_smartreflex_mpu_irqs,
.main_clk = "smartreflex_mpu_fck",
.vdd_name = "mpu",
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET,
@ -4104,6 +4116,7 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
},
.slaves = omap44xx_smartreflex_mpu_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
.dev_attr = &smartreflex_mpu_dev_attr,
};
/*

View File

@ -29,6 +29,7 @@ static int sr_class3_enable(struct voltagedomain *voltdm)
static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
{
sr_disable_errgen(voltdm);
omap_vp_disable(voltdm);
sr_disable(voltdm);
if (is_volt_reset)

View File

@ -36,6 +36,12 @@
#define SR_DISABLE_TIMEOUT 200
struct omap_sr {
struct list_head node;
struct platform_device *pdev;
struct omap_sr_nvalue_table *nvalue_table;
struct voltagedomain *voltdm;
struct dentry *dbg_dir;
unsigned int irq;
int srid;
int ip_type;
int nvalue_count;
@ -49,13 +55,7 @@ struct omap_sr {
u32 senp_avgweight;
u32 senp_mod;
u32 senn_mod;
unsigned int irq;
void __iomem *base;
struct platform_device *pdev;
struct list_head node;
struct omap_sr_nvalue_table *nvalue_table;
struct voltagedomain *voltdm;
struct dentry *dbg_dir;
};
/* sr_list contains all the instances of smartreflex module */
@ -74,10 +74,6 @@ static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
u32 value)
{
u32 reg_val;
u32 errconfig_offs = 0, errconfig_mask = 0;
reg_val = __raw_readl(sr->base + offset);
reg_val &= ~mask;
/*
* Smartreflex error config register is special as it contains
@ -88,16 +84,15 @@ static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
* if they are currently set, but does allow the caller to write
* those bits.
*/
if (sr->ip_type == SR_TYPE_V1) {
errconfig_offs = ERRCONFIG_V1;
errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
} else if (sr->ip_type == SR_TYPE_V2) {
errconfig_offs = ERRCONFIG_V2;
errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
}
if (sr->ip_type == SR_TYPE_V1 && offset == ERRCONFIG_V1)
mask |= ERRCONFIG_STATUS_V1_MASK;
else if (sr->ip_type == SR_TYPE_V2 && offset == ERRCONFIG_V2)
mask |= ERRCONFIG_VPBOUNDINTST_V2;
if (offset == errconfig_offs)
reg_val &= ~errconfig_mask;
reg_val = __raw_readl(sr->base + offset);
reg_val &= ~mask;
value &= mask;
reg_val |= value;
@ -128,21 +123,28 @@ static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
static irqreturn_t sr_interrupt(int irq, void *data)
{
struct omap_sr *sr_info = (struct omap_sr *)data;
struct omap_sr *sr_info = data;
u32 status = 0;
if (sr_info->ip_type == SR_TYPE_V1) {
switch (sr_info->ip_type) {
case SR_TYPE_V1:
/* Read the status bits */
status = sr_read_reg(sr_info, ERRCONFIG_V1);
/* Clear them by writing back */
sr_write_reg(sr_info, ERRCONFIG_V1, status);
} else if (sr_info->ip_type == SR_TYPE_V2) {
break;
case SR_TYPE_V2:
/* Read the status bits */
status = sr_read_reg(sr_info, IRQSTATUS);
/* Clear them by writing back */
sr_write_reg(sr_info, IRQSTATUS, status);
break;
default:
dev_err(&sr_info->pdev->dev, "UNKNOWN IP type %d\n",
sr_info->ip_type);
return IRQ_NONE;
}
if (sr_class->notify)
@ -166,6 +168,7 @@ static void sr_set_clk_length(struct omap_sr *sr)
__func__);
return;
}
sys_clk_speed = clk_get_rate(sys_ck);
clk_put(sys_ck);
@ -267,7 +270,7 @@ static int sr_late_init(struct omap_sr *sr_info)
goto error;
}
ret = request_irq(sr_info->irq, sr_interrupt,
0, name, (void *)sr_info);
0, name, sr_info);
if (ret)
goto error;
disable_irq(sr_info->irq);
@ -288,12 +291,15 @@ error:
"not function as desired\n", __func__);
kfree(name);
kfree(sr_info);
return ret;
}
static void sr_v1_disable(struct omap_sr *sr)
{
int timeout = 0;
int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
ERRCONFIG_MCUBOUNDINTST;
/* Enable MCUDisableAcknowledge interrupt */
sr_modify_reg(sr, ERRCONFIG_V1,
@ -302,13 +308,13 @@ static void sr_v1_disable(struct omap_sr *sr)
/* SRCONFIG - disable SR */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
/* Disable all other SR interrupts and clear the status */
/* Disable all other SR interrupts and clear the status as needed */
if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1)
errconf_val |= ERRCONFIG_VPBOUNDINTST_V1;
sr_modify_reg(sr, ERRCONFIG_V1,
(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
(ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
ERRCONFIG_MCUBOUNDINTST |
ERRCONFIG_VPBOUNDINTST_V1));
errconf_val);
/*
* Wait for SR to be disabled.
@ -337,9 +343,17 @@ static void sr_v2_disable(struct omap_sr *sr)
/* SRCONFIG - disable SR */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
/* Disable all other SR interrupts and clear the status */
sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
/*
* Disable all other SR interrupts and clear the status
* write to status register ONLY on need basis - only if status
* is set.
*/
if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2)
sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
ERRCONFIG_VPBOUNDINTST_V2);
else
sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
0x0);
sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
IRQENABLE_MCUVALIDINT |
IRQENABLE_MCUBOUNDSINT));
@ -398,15 +412,16 @@ static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
*/
int sr_configure_errgen(struct voltagedomain *voltdm)
{
u32 sr_config, sr_errconfig, errconfig_offs, vpboundint_en;
u32 vpboundint_st, senp_en = 0, senn_en = 0;
u32 sr_config, sr_errconfig, errconfig_offs;
u32 vpboundint_en, vpboundint_st;
u32 senp_en = 0, senn_en = 0;
u8 senp_shift, senn_shift;
struct omap_sr *sr = _sr_lookup(voltdm);
if (IS_ERR(sr)) {
pr_warning("%s: omap_sr struct for sr_%s not found\n",
__func__, voltdm->name);
return -EINVAL;
return PTR_ERR(sr);
}
if (!sr->clk_length)
@ -418,20 +433,23 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
if (sr->ip_type == SR_TYPE_V1) {
switch (sr->ip_type) {
case SR_TYPE_V1:
sr_config |= SRCONFIG_DELAYCTRL;
senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
errconfig_offs = ERRCONFIG_V1;
vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
} else if (sr->ip_type == SR_TYPE_V2) {
break;
case SR_TYPE_V2:
senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
errconfig_offs = ERRCONFIG_V2;
vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
} else {
break;
default:
dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
"module without specifying the ip\n", __func__);
return -EINVAL;
@ -447,8 +465,55 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
sr_errconfig);
/* Enabling the interrupts if the ERROR module is used */
sr_modify_reg(sr, errconfig_offs,
vpboundint_en, (vpboundint_en | vpboundint_st));
sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st),
vpboundint_en);
return 0;
}
/**
* sr_disable_errgen() - Disables SmartReflex AVS module's errgen component
* @voltdm: VDD pointer to which the SR module to be configured belongs to.
*
* This API is to be called from the smartreflex class driver to
* disable the error generator module inside the smartreflex module.
*
* Returns 0 on success and error value in case of failure.
*/
int sr_disable_errgen(struct voltagedomain *voltdm)
{
u32 errconfig_offs;
u32 vpboundint_en, vpboundint_st;
struct omap_sr *sr = _sr_lookup(voltdm);
if (IS_ERR(sr)) {
pr_warning("%s: omap_sr struct for sr_%s not found\n",
__func__, voltdm->name);
return PTR_ERR(sr);
}
switch (sr->ip_type) {
case SR_TYPE_V1:
errconfig_offs = ERRCONFIG_V1;
vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
break;
case SR_TYPE_V2:
errconfig_offs = ERRCONFIG_V2;
vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
break;
default:
dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
"module without specifying the ip\n", __func__);
return -EINVAL;
}
/* Disable the interrupts of ERROR module */
sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0);
/* Disable the Sensor and errorgen */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0);
return 0;
}
@ -475,7 +540,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
if (IS_ERR(sr)) {
pr_warning("%s: omap_sr struct for sr_%s not found\n",
__func__, voltdm->name);
return -EINVAL;
return PTR_ERR(sr);
}
if (!sr->clk_length)
@ -488,14 +553,17 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
SRCONFIG_SENENABLE |
(sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
if (sr->ip_type == SR_TYPE_V1) {
switch (sr->ip_type) {
case SR_TYPE_V1:
sr_config |= SRCONFIG_DELAYCTRL;
senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
} else if (sr->ip_type == SR_TYPE_V2) {
break;
case SR_TYPE_V2:
senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
} else {
break;
default:
dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
"module without specifying the ip\n", __func__);
return -EINVAL;
@ -511,20 +579,27 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
* Enabling the interrupts if MINMAXAVG module is used.
* TODO: check if all the interrupts are mandatory
*/
if (sr->ip_type == SR_TYPE_V1) {
switch (sr->ip_type) {
case SR_TYPE_V1:
sr_modify_reg(sr, ERRCONFIG_V1,
(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
ERRCONFIG_MCUBOUNDINTEN),
(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
} else if (sr->ip_type == SR_TYPE_V2) {
break;
case SR_TYPE_V2:
sr_write_reg(sr, IRQSTATUS,
IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
sr_write_reg(sr, IRQENABLE_SET,
IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
break;
default:
dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
"module without specifying the ip\n", __func__);
return -EINVAL;
}
return 0;
@ -543,15 +618,15 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
*/
int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
{
u32 nvalue_reciprocal;
struct omap_volt_data *volt_data;
struct omap_sr *sr = _sr_lookup(voltdm);
u32 nvalue_reciprocal;
int ret;
if (IS_ERR(sr)) {
pr_warning("%s: omap_sr struct for sr_%s not found\n",
__func__, voltdm->name);
return -EINVAL;
return PTR_ERR(sr);
}
volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
@ -559,7 +634,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
if (IS_ERR(volt_data)) {
dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
"for nominal voltage %ld\n", __func__, volt);
return -ENODATA;
return PTR_ERR(volt_data);
}
nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs);
@ -617,10 +692,17 @@ void sr_disable(struct voltagedomain *voltdm)
* disable the clocks.
*/
if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
if (sr->ip_type == SR_TYPE_V1)
switch (sr->ip_type) {
case SR_TYPE_V1:
sr_v1_disable(sr);
else if (sr->ip_type == SR_TYPE_V2)
break;
case SR_TYPE_V2:
sr_v2_disable(sr);
break;
default:
dev_err(&sr->pdev->dev, "UNKNOWN IP type %d\n",
sr->ip_type);
}
}
pm_runtime_put_sync_suspend(&sr->pdev->dev);
@ -779,10 +861,10 @@ void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data)
sr_pmic_data = pmic_data;
}
/* PM Debug Fs enteries to enable disable smartreflex. */
/* PM Debug FS entries to enable and disable smartreflex. */
static int omap_sr_autocomp_show(void *data, u64 *val)
{
struct omap_sr *sr_info = (struct omap_sr *) data;
struct omap_sr *sr_info = data;
if (!sr_info) {
pr_warning("%s: omap_sr struct not found\n", __func__);
@ -796,7 +878,7 @@ static int omap_sr_autocomp_show(void *data, u64 *val)
static int omap_sr_autocomp_store(void *data, u64 val)
{
struct omap_sr *sr_info = (struct omap_sr *) data;
struct omap_sr *sr_info = data;
if (!sr_info) {
pr_warning("%s: omap_sr struct not found\n", __func__);
@ -804,7 +886,7 @@ static int omap_sr_autocomp_store(void *data, u64 val)
}
/* Sanity check */
if (val && (val != 1)) {
if (val > 1) {
pr_warning("%s: Invalid argument %lld\n", __func__, val);
return -EINVAL;
}
@ -821,11 +903,11 @@ static int omap_sr_autocomp_store(void *data, u64 val)
}
DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
omap_sr_autocomp_store, "%llu\n");
omap_sr_autocomp_store, "%llu\n");
static int __init omap_sr_probe(struct platform_device *pdev)
{
struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
struct omap_sr *sr_info;
struct omap_sr_data *pdata = pdev->dev.platform_data;
struct resource *mem, *irq;
struct dentry *nvalue_dir;
@ -833,12 +915,15 @@ static int __init omap_sr_probe(struct platform_device *pdev)
int i, ret = 0;
char *name;
sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
if (!sr_info) {
dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
__func__);
return -ENOMEM;
}
platform_set_drvdata(pdev, sr_info);
if (!pdata) {
dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
ret = -EINVAL;
@ -904,7 +989,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
if (!sr_dbg_dir) {
sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
if (!sr_dbg_dir) {
if (IS_ERR_OR_NULL(sr_dbg_dir)) {
ret = PTR_ERR(sr_dbg_dir);
pr_err("%s:sr debugfs dir creation failed(%d)\n",
__func__, ret);
@ -921,7 +1006,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
}
sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
kfree(name);
if (IS_ERR(sr_info->dbg_dir)) {
if (IS_ERR_OR_NULL(sr_info->dbg_dir)) {
dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
__func__);
ret = PTR_ERR(sr_info->dbg_dir);
@ -938,7 +1023,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
&sr_info->err_minlimit);
nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
if (IS_ERR(nvalue_dir)) {
if (IS_ERR_OR_NULL(nvalue_dir)) {
dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
"for n-values\n", __func__);
ret = PTR_ERR(nvalue_dir);
@ -994,7 +1079,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
if (IS_ERR(sr_info)) {
dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
__func__);
return -EINVAL;
return PTR_ERR(sr_info);
}
if (sr_info->autocomp_active)
@ -1011,8 +1096,32 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
return 0;
}
static void __devexit omap_sr_shutdown(struct platform_device *pdev)
{
struct omap_sr_data *pdata = pdev->dev.platform_data;
struct omap_sr *sr_info;
if (!pdata) {
dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
return;
}
sr_info = _sr_lookup(pdata->voltdm);
if (IS_ERR(sr_info)) {
dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
__func__);
return;
}
if (sr_info->autocomp_active)
sr_stop_vddautocomp(sr_info);
return;
}
static struct platform_driver smartreflex_driver = {
.remove = __devexit_p(omap_sr_remove),
.shutdown = __devexit_p(omap_sr_shutdown),
.driver = {
.name = "smartreflex",
},
@ -1042,12 +1151,12 @@ static int __init sr_init(void)
return 0;
}
late_initcall(sr_init);
static void __exit sr_exit(void)
{
platform_driver_unregister(&smartreflex_driver);
}
late_initcall(sr_init);
module_exit(sr_exit);
MODULE_DESCRIPTION("OMAP Smartreflex Driver");

View File

@ -152,6 +152,15 @@ struct omap_sr_pmic_data {
void (*sr_pmic_init) (void);
};
/**
* struct omap_smartreflex_dev_attr - Smartreflex Device attribute.
*
* @sensor_voltdm_name: Name of voltdomain of SR instance
*/
struct omap_smartreflex_dev_attr {
const char *sensor_voltdm_name;
};
#ifdef CONFIG_OMAP_SMARTREFLEX
/*
* The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
@ -231,6 +240,7 @@ void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
void sr_disable(struct voltagedomain *voltdm);
int sr_configure_errgen(struct voltagedomain *voltdm);
int sr_disable_errgen(struct voltagedomain *voltdm);
int sr_configure_minmax(struct voltagedomain *voltdm);
/* API to register the smartreflex class driver with the smartreflex driver */

View File

@ -74,6 +74,7 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
struct omap_sr_data *sr_data;
struct platform_device *pdev;
struct omap_volt_data *volt_data;
struct omap_smartreflex_dev_attr *sr_dev_attr;
char *name = "smartreflex";
static int i;
@ -84,9 +85,11 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
return -ENOMEM;
}
if (!oh->vdd_name) {
sr_dev_attr = (struct omap_smartreflex_dev_attr *)oh->dev_attr;
if (!sr_dev_attr || !sr_dev_attr->sensor_voltdm_name) {
pr_err("%s: No voltage domain specified for %s."
"Cannot initialize\n", __func__, oh->name);
"Cannot initialize\n", __func__,
oh->name);
goto exit;
}
@ -94,10 +97,10 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
sr_data->senn_mod = 0x1;
sr_data->senp_mod = 0x1;
sr_data->voltdm = voltdm_lookup(oh->vdd_name);
sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name);
if (IS_ERR(sr_data->voltdm)) {
pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
__func__, oh->vdd_name);
__func__, sr_dev_attr->sensor_voltdm_name);
goto exit;
}

View File

@ -406,20 +406,17 @@ static struct resource pxa_rtc_resources[] = {
[1] = {
.start = IRQ_RTC1Hz,
.end = IRQ_RTC1Hz,
.name = "rtc 1Hz",
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = IRQ_RTCAlrm,
.end = IRQ_RTCAlrm,
.name = "rtc alarm",
.flags = IORESOURCE_IRQ,
},
};
struct platform_device sa1100_device_rtc = {
.name = "sa1100-rtc",
.id = -1,
};
struct platform_device pxa_device_rtc = {
.name = "pxa-rtc",
.id = -1,
@ -427,6 +424,27 @@ struct platform_device pxa_device_rtc = {
.resource = pxa_rtc_resources,
};
static struct resource sa1100_rtc_resources[] = {
{
.start = IRQ_RTC1Hz,
.end = IRQ_RTC1Hz,
.name = "rtc 1Hz",
.flags = IORESOURCE_IRQ,
}, {
.start = IRQ_RTCAlrm,
.end = IRQ_RTCAlrm,
.name = "rtc alarm",
.flags = IORESOURCE_IRQ,
},
};
struct platform_device sa1100_device_rtc = {
.name = "sa1100-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(sa1100_rtc_resources),
.resource = sa1100_rtc_resources,
};
static struct resource pxa_ac97_resources[] = {
[0] = {
.start = 0x40500000,

View File

@ -28,7 +28,8 @@
#include <linux/mtd/physmap.h>
#include <linux/pda_power.h>
#include <linux/pwm_backlight.h>
#include <linux/regulator/bq24022.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/gpio-regulator.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/max1586.h>
#include <linux/spi/ads7846.h>
@ -698,14 +699,34 @@ static struct regulator_init_data bq24022_init_data = {
.consumer_supplies = bq24022_consumers,
};
static struct bq24022_mach_info bq24022_info = {
.gpio_nce = GPIO72_HX4700_BQ24022_nCHARGE_EN,
.gpio_iset2 = GPIO96_HX4700_BQ24022_ISET2,
.init_data = &bq24022_init_data,
static struct gpio bq24022_gpios[] = {
{ GPIO96_HX4700_BQ24022_ISET2, GPIOF_OUT_INIT_LOW, "bq24022_iset2" },
};
static struct gpio_regulator_state bq24022_states[] = {
{ .value = 100000, .gpios = (0 << 0) },
{ .value = 500000, .gpios = (1 << 0) },
};
static struct gpio_regulator_config bq24022_info = {
.supply_name = "bq24022",
.enable_gpio = GPIO72_HX4700_BQ24022_nCHARGE_EN,
.enable_high = 0,
.enabled_at_boot = 0,
.gpios = bq24022_gpios,
.nr_gpios = ARRAY_SIZE(bq24022_gpios),
.states = bq24022_states,
.nr_states = ARRAY_SIZE(bq24022_states),
.type = REGULATOR_CURRENT,
.init_data = &bq24022_init_data,
};
static struct platform_device bq24022 = {
.name = "bq24022",
.name = "gpio-regulator",
.id = -1,
.dev = {
.platform_data = &bq24022_info,

View File

@ -25,7 +25,8 @@
#include <linux/mtd/physmap.h>
#include <linux/pda_power.h>
#include <linux/pwm_backlight.h>
#include <linux/regulator/bq24022.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/gpio-regulator.h>
#include <linux/regulator/machine.h>
#include <linux/usb/gpio_vbus.h>
#include <linux/i2c/pxa-i2c.h>
@ -596,14 +597,34 @@ static struct regulator_init_data bq24022_init_data = {
.consumer_supplies = bq24022_consumers,
};
static struct bq24022_mach_info bq24022_info = {
.gpio_nce = GPIO30_MAGICIAN_BQ24022_nCHARGE_EN,
.gpio_iset2 = EGPIO_MAGICIAN_BQ24022_ISET2,
.init_data = &bq24022_init_data,
static struct gpio bq24022_gpios[] = {
{ EGPIO_MAGICIAN_BQ24022_ISET2, GPIOF_OUT_INIT_LOW, "bq24022_iset2" },
};
static struct gpio_regulator_state bq24022_states[] = {
{ .value = 100000, .gpios = (0 << 0) },
{ .value = 500000, .gpios = (1 << 0) },
};
static struct gpio_regulator_config bq24022_info = {
.supply_name = "bq24022",
.enable_gpio = GPIO30_MAGICIAN_BQ24022_nCHARGE_EN,
.enable_high = 0,
.enabled_at_boot = 0,
.gpios = bq24022_gpios,
.nr_gpios = ARRAY_SIZE(bq24022_gpios),
.states = bq24022_states,
.nr_states = ARRAY_SIZE(bq24022_states),
.type = REGULATOR_CURRENT,
.init_data = &bq24022_init_data,
};
static struct platform_device bq24022 = {
.name = "bq24022",
.name = "gpio-regulator",
.id = -1,
.dev = {
.platform_data = &bq24022_info,

View File

@ -89,6 +89,7 @@ static struct clk_lookup pxa3xx_clkregs[] = {
INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL),
INIT_CLKREG(&clk_pxa3xx_smemc, "pxa2xx-pcmcia", NULL),
INIT_CLKREG(&clk_pxa3xx_gpio, "pxa-gpio", NULL),
INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
#ifdef CONFIG_PM

View File

@ -231,6 +231,7 @@ static struct clk_lookup pxa95x_clkregs[] = {
INIT_CLKREG(&clk_pxa95x_pwm0, "pxa27x-pwm.0", NULL),
INIT_CLKREG(&clk_pxa95x_pwm1, "pxa27x-pwm.1", NULL),
INIT_CLKREG(&clk_pxa95x_gpio, "pxa-gpio", NULL),
INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
void __init pxa95x_init_irq(void)

View File

@ -59,6 +59,7 @@
#include <plat/fb-core.h>
#include <plat/nand-core.h>
#include <plat/adc-core.h>
#include <plat/rtc-core.h>
static struct map_desc s3c2416_iodesc[] __initdata = {
IODESC_ENT(WATCHDOG),
@ -98,6 +99,7 @@ int __init s3c2416_init(void)
s3c_fb_setname("s3c2443-fb");
s3c_adc_setname("s3c2416-adc");
s3c_rtc_setname("s3c2416-rtc");
#ifdef CONFIG_PM
register_syscore_ops(&s3c2416_pm_syscore_ops);

View File

@ -41,6 +41,7 @@
#include <plat/fb-core.h>
#include <plat/nand-core.h>
#include <plat/adc-core.h>
#include <plat/rtc-core.h>
static struct map_desc s3c2443_iodesc[] __initdata = {
IODESC_ENT(WATCHDOG),
@ -73,6 +74,7 @@ int __init s3c2443_init(void)
s3c_fb_setname("s3c2443-fb");
s3c_adc_setname("s3c2443-adc");
s3c_rtc_setname("s3c2443-rtc");
/* change WDT IRQ number */
s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT;

View File

@ -11,17 +11,29 @@
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <mach/hardware.h>
/*
* Very simple clock implementation - we only have one clock to deal with.
*/
struct clkops {
void (*enable)(struct clk *);
void (*disable)(struct clk *);
};
struct clk {
const struct clkops *ops;
unsigned int enabled;
};
static void clk_gpio27_enable(void)
#define DEFINE_CLK(_name, _ops) \
struct clk clk_##_name = { \
.ops = _ops, \
}
static DEFINE_SPINLOCK(clocks_lock);
static void clk_gpio27_enable(struct clk *clk)
{
/*
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
@ -32,38 +44,24 @@ static void clk_gpio27_enable(void)
TUCR = TUCR_3_6864MHz;
}
static void clk_gpio27_disable(void)
static void clk_gpio27_disable(struct clk *clk)
{
TUCR = 0;
GPDR &= ~GPIO_32_768kHz;
GAFR &= ~GPIO_32_768kHz;
}
static struct clk clk_gpio27;
static DEFINE_SPINLOCK(clocks_lock);
struct clk *clk_get(struct device *dev, const char *id)
{
const char *devname = dev_name(dev);
return strcmp(devname, "sa1111.0") ? ERR_PTR(-ENOENT) : &clk_gpio27;
}
EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_put);
int clk_enable(struct clk *clk)
{
unsigned long flags;
spin_lock_irqsave(&clocks_lock, flags);
if (clk->enabled++ == 0)
clk_gpio27_enable();
spin_unlock_irqrestore(&clocks_lock, flags);
if (clk) {
spin_lock_irqsave(&clocks_lock, flags);
if (clk->enabled++ == 0)
clk->ops->enable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
}
return 0;
}
EXPORT_SYMBOL(clk_enable);
@ -72,17 +70,31 @@ void clk_disable(struct clk *clk)
{
unsigned long flags;
WARN_ON(clk->enabled == 0);
spin_lock_irqsave(&clocks_lock, flags);
if (--clk->enabled == 0)
clk_gpio27_disable();
spin_unlock_irqrestore(&clocks_lock, flags);
if (clk) {
WARN_ON(clk->enabled == 0);
spin_lock_irqsave(&clocks_lock, flags);
if (--clk->enabled == 0)
clk->ops->disable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
}
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate(struct clk *clk)
const struct clkops clk_gpio27_ops = {
.enable = clk_gpio27_enable,
.disable = clk_gpio27_disable,
};
static DEFINE_CLK(gpio27, &clk_gpio27_ops);
static struct clk_lookup sa11xx_clkregs[] = {
CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27),
CLKDEV_INIT("sa1100-rtc", NULL, NULL),
};
static int __init sa11xx_clk_init(void)
{
return 3686400;
clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
return 0;
}
EXPORT_SYMBOL(clk_get_rate);
core_initcall(sa11xx_clk_init);

View File

@ -345,9 +345,17 @@ void sa11x0_register_irda(struct irda_platform_data *irda)
sa11x0_register_device(&sa11x0ir_device, irda);
}
static struct resource sa1100_rtc_resources[] = {
DEFINE_RES_MEM(0x90010000, 0x9001003f),
DEFINE_RES_IRQ_NAMED(IRQ_RTC1Hz, "rtc 1Hz"),
DEFINE_RES_IRQ_NAMED(IRQ_RTCAlrm, "rtc alarm"),
};
static struct platform_device sa11x0rtc_device = {
.name = "sa1100-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(sa1100_rtc_resources),
.resource = sa1100_rtc_resources,
};
static struct platform_device *sa11x0_devices[] __initdata = {

View File

@ -7,6 +7,7 @@ obj-y += clock.o
obj-y += timer.o
obj-y += pinmux.o
obj-y += fuse.o
obj-y += pmc.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_CPU_IDLE) += sleep.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += powergate.o
@ -18,7 +19,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o
obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o apbio.o
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
obj-$(CONFIG_TEGRA_PCI) += pcie.o
obj-$(CONFIG_USB_SUPPORT) += usb_phy.o

145
arch/arm/mach-tegra/apbio.c Normal file
View File

@ -0,0 +1,145 @@
/*
* Copyright (C) 2010 NVIDIA Corporation.
* Copyright (C) 2010 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/mutex.h>
#include <mach/dma.h>
#include <mach/iomap.h>
#include "apbio.h"
static DEFINE_MUTEX(tegra_apb_dma_lock);
static struct tegra_dma_channel *tegra_apb_dma;
static u32 *tegra_apb_bb;
static dma_addr_t tegra_apb_bb_phys;
static DECLARE_COMPLETION(tegra_apb_wait);
bool tegra_apb_init(void)
{
struct tegra_dma_channel *ch;
mutex_lock(&tegra_apb_dma_lock);
/* Check to see if we raced to setup */
if (tegra_apb_dma)
goto out;
ch = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT |
TEGRA_DMA_SHARED);
if (!ch)
goto out_fail;
tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
&tegra_apb_bb_phys, GFP_KERNEL);
if (!tegra_apb_bb) {
pr_err("%s: can not allocate bounce buffer\n", __func__);
tegra_dma_free_channel(ch);
goto out_fail;
}
tegra_apb_dma = ch;
out:
mutex_unlock(&tegra_apb_dma_lock);
return true;
out_fail:
mutex_unlock(&tegra_apb_dma_lock);
return false;
}
static void apb_dma_complete(struct tegra_dma_req *req)
{
complete(&tegra_apb_wait);
}
u32 tegra_apb_readl(unsigned long offset)
{
struct tegra_dma_req req;
int ret;
if (!tegra_apb_dma && !tegra_apb_init())
return readl(IO_TO_VIRT(offset));
mutex_lock(&tegra_apb_dma_lock);
req.complete = apb_dma_complete;
req.to_memory = 1;
req.dest_addr = tegra_apb_bb_phys;
req.dest_bus_width = 32;
req.dest_wrap = 1;
req.source_addr = offset;
req.source_bus_width = 32;
req.source_wrap = 4;
req.req_sel = TEGRA_DMA_REQ_SEL_CNTR;
req.size = 4;
INIT_COMPLETION(tegra_apb_wait);
tegra_dma_enqueue_req(tegra_apb_dma, &req);
ret = wait_for_completion_timeout(&tegra_apb_wait,
msecs_to_jiffies(50));
if (WARN(ret == 0, "apb read dma timed out")) {
tegra_dma_dequeue_req(tegra_apb_dma, &req);
*(u32 *)tegra_apb_bb = 0;
}
mutex_unlock(&tegra_apb_dma_lock);
return *((u32 *)tegra_apb_bb);
}
void tegra_apb_writel(u32 value, unsigned long offset)
{
struct tegra_dma_req req;
int ret;
if (!tegra_apb_dma && !tegra_apb_init()) {
writel(value, IO_TO_VIRT(offset));
return;
}
mutex_lock(&tegra_apb_dma_lock);
*((u32 *)tegra_apb_bb) = value;
req.complete = apb_dma_complete;
req.to_memory = 0;
req.dest_addr = offset;
req.dest_wrap = 4;
req.dest_bus_width = 32;
req.source_addr = tegra_apb_bb_phys;
req.source_bus_width = 32;
req.source_wrap = 1;
req.req_sel = TEGRA_DMA_REQ_SEL_CNTR;
req.size = 4;
INIT_COMPLETION(tegra_apb_wait);
tegra_dma_enqueue_req(tegra_apb_dma, &req);
ret = wait_for_completion_timeout(&tegra_apb_wait,
msecs_to_jiffies(50));
if (WARN(ret == 0, "apb write dma timed out"))
tegra_dma_dequeue_req(tegra_apb_dma, &req);
mutex_unlock(&tegra_apb_dma_lock);
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2010 NVIDIA Corporation.
* Copyright (C) 2010 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#ifndef __MACH_TEGRA_APBIO_H
#define __MACH_TEGRA_APBIO_H
#ifdef CONFIG_TEGRA_SYSTEM_DMA
u32 tegra_apb_readl(unsigned long offset);
void tegra_apb_writel(u32 value, unsigned long offset);
#else
#include <asm/io.h>
#include <mach/io.h>
static inline u32 tegra_apb_readl(unsigned long offset)
{
return readl(IO_TO_VIRT(offset));
}
static inline void tegra_apb_writel(u32 value, unsigned long offset)
{
writel(value, IO_TO_VIRT(offset));
}
#endif
#endif

View File

@ -18,18 +18,13 @@
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/tps6586x.h>
#include <mach/iomap.h>
#include <mach/irqs.h>
#include "board-harmony.h"
#define PMC_CTRL 0x0
#define PMC_CTRL_INTR_LOW (1 << 17)
static struct regulator_consumer_supply tps658621_ldo0_supply[] = {
REGULATOR_SUPPLY("pex_clk", NULL),
};
@ -115,16 +110,6 @@ static struct i2c_board_info __initdata harmony_regulators[] = {
int __init harmony_regulator_init(void)
{
void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
u32 pmc_ctrl;
/*
* Configure the power management controller to trigger PMU
* interrupts when low
*/
pmc_ctrl = readl(pmc + PMC_CTRL);
writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
i2c_register_board_info(3, harmony_regulators, 1);
return 0;

View File

@ -101,7 +101,6 @@ static struct wm8903_platform_data harmony_wm8903_pdata = {
static struct i2c_board_info __initdata wm8903_board_info = {
I2C_BOARD_INFO("wm8903", 0x1a),
.platform_data = &harmony_wm8903_pdata,
.irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
};
static void __init harmony_i2c_init(void)
@ -111,6 +110,7 @@ static void __init harmony_i2c_init(void)
platform_device_register(&tegra_i2c_device3);
platform_device_register(&tegra_i2c_device4);
wm8903_board_info.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
i2c_register_board_info(0, &wm8903_board_info, 1);
}

View File

@ -159,7 +159,6 @@ static struct platform_device *seaboard_devices[] __initdata = {
static struct i2c_board_info __initdata isl29018_device = {
I2C_BOARD_INFO("isl29018", 0x44),
.irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_ISL29018_IRQ),
};
static struct i2c_board_info __initdata adt7461_device = {
@ -183,7 +182,6 @@ static struct wm8903_platform_data wm8903_pdata = {
static struct i2c_board_info __initdata wm8903_device = {
I2C_BOARD_INFO("wm8903", 0x1a),
.platform_data = &wm8903_pdata,
.irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
};
static int seaboard_ehci_init(void)
@ -214,7 +212,10 @@ static void __init seaboard_i2c_init(void)
gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018");
gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ);
isl29018_device.irq = gpio_to_irq(TEGRA_GPIO_ISL29018_IRQ);
i2c_register_board_info(0, &isl29018_device, 1);
wm8903_device.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
i2c_register_board_info(0, &wm8903_device, 1);
i2c_register_board_info(3, &adt7461_device, 1);

View File

@ -31,6 +31,24 @@
#include "board.h"
#include "clock.h"
#include "fuse.h"
#include "pmc.h"
/*
* Storage for debug-macro.S's state.
*
* This must be in .data not .bss so that it gets initialized each time the
* kernel is loaded. The data is declared here rather than debug-macro.S so
* that multiple inclusions of debug-macro.S point at the same data.
*/
#define TEGRA_DEBUG_UART_OFFSET (TEGRA_DEBUG_UART_BASE & 0xFFFF)
u32 tegra_uart_config[3] = {
/* Debug UART initialization required */
1,
/* Debug UART physical address */
(u32)(IO_APB_PHYS + TEGRA_DEBUG_UART_OFFSET),
/* Debug UART virtual address */
(u32)(IO_APB_VIRT + TEGRA_DEBUG_UART_OFFSET),
};
#ifdef CONFIG_OF
static const struct of_device_id tegra_dt_irq_match[] __initconst = {
@ -99,6 +117,7 @@ void __init tegra20_init_early(void)
tegra2_init_clocks();
tegra_clk_init_from_table(tegra20_clk_init_table);
tegra_init_cache(0x331, 0x441);
tegra_pmc_init();
}
#endif
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
@ -106,5 +125,6 @@ void __init tegra30_init_early(void)
{
tegra30_init_clocks();
tegra_init_cache(0x441, 0x551);
tegra_pmc_init();
}
#endif

View File

@ -33,6 +33,8 @@
#include <mach/iomap.h>
#include <mach/suspend.h>
#include "apbio.h"
#define APB_DMA_GEN 0x000
#define GEN_ENABLE (1<<31)
@ -50,8 +52,6 @@
#define CSR_ONCE (1<<27)
#define CSR_FLOW (1<<21)
#define CSR_REQ_SEL_SHIFT 16
#define CSR_REQ_SEL_MASK (0x1F<<CSR_REQ_SEL_SHIFT)
#define CSR_REQ_SEL_INVALID (31<<CSR_REQ_SEL_SHIFT)
#define CSR_WCOUNT_SHIFT 2
#define CSR_WCOUNT_MASK 0xFFFC
@ -133,6 +133,7 @@ struct tegra_dma_channel {
static bool tegra_dma_initialized;
static DEFINE_MUTEX(tegra_dma_lock);
static DEFINE_SPINLOCK(enable_lock);
static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
@ -180,36 +181,94 @@ static void tegra_dma_stop(struct tegra_dma_channel *ch)
static int tegra_dma_cancel(struct tegra_dma_channel *ch)
{
u32 csr;
unsigned long irq_flags;
spin_lock_irqsave(&ch->lock, irq_flags);
while (!list_empty(&ch->list))
list_del(ch->list.next);
csr = readl(ch->addr + APB_DMA_CHAN_CSR);
csr &= ~CSR_REQ_SEL_MASK;
csr |= CSR_REQ_SEL_INVALID;
writel(csr, ch->addr + APB_DMA_CHAN_CSR);
tegra_dma_stop(ch);
spin_unlock_irqrestore(&ch->lock, irq_flags);
return 0;
}
static unsigned int get_channel_status(struct tegra_dma_channel *ch,
struct tegra_dma_req *req, bool is_stop_dma)
{
void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
unsigned int status;
if (is_stop_dma) {
/*
* STOP the DMA and get the transfer count.
* Getting the transfer count is tricky.
* - Globally disable DMA on all channels
* - Read the channel's status register to know the number
* of pending bytes to be transfered.
* - Stop the dma channel
* - Globally re-enable DMA to resume other transfers
*/
spin_lock(&enable_lock);
writel(0, addr + APB_DMA_GEN);
udelay(20);
status = readl(ch->addr + APB_DMA_CHAN_STA);
tegra_dma_stop(ch);
writel(GEN_ENABLE, addr + APB_DMA_GEN);
spin_unlock(&enable_lock);
if (status & STA_ISE_EOC) {
pr_err("Got Dma Int here clearing");
writel(status, ch->addr + APB_DMA_CHAN_STA);
}
req->status = TEGRA_DMA_REQ_ERROR_ABORTED;
} else {
status = readl(ch->addr + APB_DMA_CHAN_STA);
}
return status;
}
/* should be called with the channel lock held */
static unsigned int dma_active_count(struct tegra_dma_channel *ch,
struct tegra_dma_req *req, unsigned int status)
{
unsigned int to_transfer;
unsigned int req_transfer_count;
unsigned int bytes_transferred;
to_transfer = ((status & STA_COUNT_MASK) >> STA_COUNT_SHIFT) + 1;
req_transfer_count = ch->req_transfer_count + 1;
bytes_transferred = req_transfer_count;
if (status & STA_BUSY)
bytes_transferred -= to_transfer;
/*
* In continuous transfer mode, DMA only tracks the count of the
* half DMA buffer. So, if the DMA already finished half the DMA
* then add the half buffer to the completed count.
*/
if (ch->mode & TEGRA_DMA_MODE_CONTINOUS) {
if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL)
bytes_transferred += req_transfer_count;
if (status & STA_ISE_EOC)
bytes_transferred += req_transfer_count;
}
bytes_transferred *= 4;
return bytes_transferred;
}
int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
struct tegra_dma_req *_req)
{
unsigned int csr;
unsigned int status;
struct tegra_dma_req *req = NULL;
int found = 0;
unsigned long irq_flags;
int to_transfer;
int req_transfer_count;
int stop = 0;
spin_lock_irqsave(&ch->lock, irq_flags);
if (list_entry(ch->list.next, struct tegra_dma_req, node) == _req)
stop = 1;
list_for_each_entry(req, &ch->list, node) {
if (req == _req) {
list_del(&req->node);
@ -222,47 +281,12 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
return 0;
}
/* STOP the DMA and get the transfer count.
* Getting the transfer count is tricky.
* - Change the source selector to invalid to stop the DMA from
* FIFO to memory.
* - Read the status register to know the number of pending
* bytes to be transferred.
* - Finally stop or program the DMA to the next buffer in the
* list.
*/
csr = readl(ch->addr + APB_DMA_CHAN_CSR);
csr &= ~CSR_REQ_SEL_MASK;
csr |= CSR_REQ_SEL_INVALID;
writel(csr, ch->addr + APB_DMA_CHAN_CSR);
if (!stop)
goto skip_stop_dma;
/* Get the transfer count */
status = readl(ch->addr + APB_DMA_CHAN_STA);
to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT;
req_transfer_count = ch->req_transfer_count;
req_transfer_count += 1;
to_transfer += 1;
status = get_channel_status(ch, req, true);
req->bytes_transferred = dma_active_count(ch, req, status);
req->bytes_transferred = req_transfer_count;
if (status & STA_BUSY)
req->bytes_transferred -= to_transfer;
/* In continuous transfer mode, DMA only tracks the count of the
* half DMA buffer. So, if the DMA already finished half the DMA
* then add the half buffer to the completed count.
*
* FIXME: There can be a race here. What if the req to
* dequue happens at the same time as the DMA just moved to
* the new buffer and SW didn't yet received the interrupt?
*/
if (ch->mode & TEGRA_DMA_MODE_CONTINOUS)
if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL)
req->bytes_transferred += req_transfer_count;
req->bytes_transferred *= 4;
tegra_dma_stop(ch);
if (!list_empty(&ch->list)) {
/* if the list is not empty, queue the next request */
struct tegra_dma_req *next_req;
@ -270,6 +294,8 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
typeof(*next_req), node);
tegra_dma_update_hw(ch, next_req);
}
skip_stop_dma:
req->status = -TEGRA_DMA_REQ_ERROR_ABORTED;
spin_unlock_irqrestore(&ch->lock, irq_flags);
@ -357,7 +383,7 @@ struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
int channel;
struct tegra_dma_channel *ch = NULL;
if (WARN_ON(!tegra_dma_initialized))
if (!tegra_dma_initialized)
return NULL;
mutex_lock(&tegra_dma_lock);

View File

@ -19,25 +19,75 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/export.h>
#include <mach/iomap.h>
#include "fuse.h"
#include "apbio.h"
#define FUSE_UID_LOW 0x108
#define FUSE_UID_HIGH 0x10c
#define FUSE_SKU_INFO 0x110
#define FUSE_SPARE_BIT 0x200
static inline u32 fuse_readl(unsigned long offset)
int tegra_sku_id;
int tegra_cpu_process_id;
int tegra_core_process_id;
enum tegra_revision tegra_revision;
/* The BCT to use at boot is specified by board straps that can be read
* through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
*/
int tegra_bct_strapping;
#define STRAP_OPT 0x008
#define GMI_AD0 (1 << 4)
#define GMI_AD1 (1 << 5)
#define RAM_ID_MASK (GMI_AD0 | GMI_AD1)
#define RAM_CODE_SHIFT 4
static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
[TEGRA_REVISION_UNKNOWN] = "unknown",
[TEGRA_REVISION_A01] = "A01",
[TEGRA_REVISION_A02] = "A02",
[TEGRA_REVISION_A03] = "A03",
[TEGRA_REVISION_A03p] = "A03 prime",
[TEGRA_REVISION_A04] = "A04",
};
static inline u32 tegra_fuse_readl(unsigned long offset)
{
return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
}
static inline void fuse_writel(u32 value, unsigned long offset)
static inline bool get_spare_fuse(int bit)
{
writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
}
static enum tegra_revision tegra_get_revision(void)
{
void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
u32 id = readl(chip_id);
u32 minor_rev = (id >> 16) & 0xf;
u32 chipid = (id >> 8) & 0xff;
switch (minor_rev) {
case 1:
return TEGRA_REVISION_A01;
case 2:
return TEGRA_REVISION_A02;
case 3:
if (chipid == 0x20 && (get_spare_fuse(18) || get_spare_fuse(19)))
return TEGRA_REVISION_A03p;
else
return TEGRA_REVISION_A03;
case 4:
return TEGRA_REVISION_A04;
default:
return TEGRA_REVISION_UNKNOWN;
}
}
void tegra_init_fuse(void)
@ -46,41 +96,32 @@ void tegra_init_fuse(void)
reg |= 1 << 28;
writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n",
tegra_sku_id(), tegra_cpu_process_id(),
tegra_core_process_id());
reg = tegra_fuse_readl(FUSE_SKU_INFO);
tegra_sku_id = reg & 0xFF;
reg = tegra_fuse_readl(FUSE_SPARE_BIT);
tegra_cpu_process_id = (reg >> 6) & 3;
reg = tegra_fuse_readl(FUSE_SPARE_BIT);
tegra_core_process_id = (reg >> 12) & 3;
reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
tegra_revision = tegra_get_revision();
pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
tegra_revision_name[tegra_get_revision()],
tegra_sku_id, tegra_cpu_process_id,
tegra_core_process_id);
}
unsigned long long tegra_chip_uid(void)
{
unsigned long long lo, hi;
lo = fuse_readl(FUSE_UID_LOW);
hi = fuse_readl(FUSE_UID_HIGH);
lo = tegra_fuse_readl(FUSE_UID_LOW);
hi = tegra_fuse_readl(FUSE_UID_HIGH);
return (hi << 32ull) | lo;
}
EXPORT_SYMBOL(tegra_chip_uid);
int tegra_sku_id(void)
{
int sku_id;
u32 reg = fuse_readl(FUSE_SKU_INFO);
sku_id = reg & 0xFF;
return sku_id;
}
int tegra_cpu_process_id(void)
{
int cpu_process_id;
u32 reg = fuse_readl(FUSE_SPARE_BIT);
cpu_process_id = (reg >> 6) & 3;
return cpu_process_id;
}
int tegra_core_process_id(void)
{
int core_process_id;
u32 reg = fuse_readl(FUSE_SPARE_BIT);
core_process_id = (reg >> 12) & 3;
return core_process_id;
}

View File

@ -1,6 +1,4 @@
/*
* arch/arm/mach-tegra/fuse.c
*
* Copyright (C) 2010 Google, Inc.
*
* Author:
@ -17,8 +15,34 @@
*
*/
#ifndef __MACH_TEGRA_FUSE_H
#define __MACH_TEGRA_FUSE_H
enum tegra_revision {
TEGRA_REVISION_UNKNOWN = 0,
TEGRA_REVISION_A01,
TEGRA_REVISION_A02,
TEGRA_REVISION_A03,
TEGRA_REVISION_A03p,
TEGRA_REVISION_A04,
TEGRA_REVISION_MAX,
};
#define SKU_ID_T20 8
#define SKU_ID_T25SE 20
#define SKU_ID_AP25 23
#define SKU_ID_T25 24
#define SKU_ID_AP25E 27
#define SKU_ID_T25E 28
extern int tegra_sku_id;
extern int tegra_cpu_process_id;
extern int tegra_core_process_id;
extern enum tegra_revision tegra_revision;
extern int tegra_bct_strapping;
unsigned long long tegra_chip_uid(void);
int tegra_sku_id(void);
int tegra_cpu_process_id(void);
int tegra_core_process_id(void);
void tegra_init_fuse(void);
#endif

View File

@ -1,11 +1,17 @@
/*
* arch/arm/mach-tegra/include/mach/debug-macro.S
*
* Copyright (C) 2010 Google, Inc.
* Copyright (C) 2010,2011 Google, Inc.
* Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
*
* Author:
* Colin Cross <ccross@google.com>
* Erik Gilling <konkers@google.com>
* Doug Anderson <dianders@chromium.org>
* Stephen Warren <swarren@nvidia.com>
*
* Portions based on mach-omap2's debug-macro.S
* Copyright (C) 1994-1999 Russell King
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@ -18,18 +24,78 @@
*
*/
#include <linux/serial_reg.h>
#include <mach/io.h>
#include <mach/iomap.h>
#include <mach/irammap.h>
.macro addruart, rp, rv, tmp
ldr \rp, =IO_APB_PHYS @ physical
ldr \rv, =IO_APB_VIRT @ virtual
orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF)
orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF)
orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
.endm
.macro addruart, rp, rv, tmp
adr \rp, 99f @ actual addr of 99f
ldr \rv, [\rp] @ linked addr is stored there
sub \rv, \rv, \rp @ offset between the two
ldr \rp, [\rp, #4] @ linked tegra_uart_config
sub \tmp, \rp, \rv @ actual tegra_uart_config
ldr \rp, [\tmp] @ Load tegra_uart_config
cmp \rp, #1 @ needs intitialization?
bne 100f @ no; go load the addresses
mov \rv, #0 @ yes; record init is done
str \rv, [\tmp]
mov \rp, #TEGRA_IRAM_BASE @ See if cookie is in IRAM
ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET]
movw \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE & 0xffff
movt \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE >> 16
cmp \rv, \rp @ Cookie present?
bne 100f @ No, use default UART
mov \rp, #TEGRA_IRAM_BASE @ Load UART address from IRAM
ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET + 4]
str \rv, [\tmp, #4] @ Store in tegra_uart_phys
sub \rv, \rv, #IO_APB_PHYS @ Calculate virt address
add \rv, \rv, #IO_APB_VIRT
str \rv, [\tmp, #8] @ Store in tegra_uart_virt
b 100f
#define UART_SHIFT 2
#include <asm/hardware/debug-8250.S>
.align
99: .word .
.word tegra_uart_config
.ltorg
100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys
ldr \rv, [\tmp, #8] @ Load tegra_uart_virt
.endm
#define UART_SHIFT 2
/*
* Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
* check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case.
* We use the fact that all 5 valid UART addresses all have something in the
* 2nd-to-lowest byte.
*/
.macro senduart, rd, rx
tst \rx, #0x0000ff00
strneb \rd, [\rx, #UART_TX << UART_SHIFT]
1001:
.endm
.macro busyuart, rd, rx
tst \rx, #0x0000ff00
beq 1002f
1001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT]
and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
teq \rd, #UART_LSR_TEMT | UART_LSR_THRE
bne 1001b
1002:
.endm
.macro waituart, rd, rx
#ifdef FLOW_CONTROL
tst \rx, #0x0000ff00
beq 1002f
1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT]
tst \rd, #UART_MSR_CTS
beq 1001b
1002:
#endif
.endm

View File

@ -25,8 +25,6 @@
#define TEGRA_NR_GPIOS INT_GPIO_NR
#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
struct tegra_gpio_table {
int gpio; /* GPIO number */
bool enable; /* Enable for GPIO at init? */

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __MACH_TEGRA_IRAMMAP_H
#define __MACH_TEGRA_IRAMMAP_H
#include <asm/sizes.h>
/* The first 1K of IRAM is permanently reserved for the CPU reset handler */
#define TEGRA_IRAM_RESET_HANDLER_OFFSET 0
#define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K
/*
* These locations are written to by uncompress.h, and read by debug-macro.S.
* The first word holds the cookie value if the data is valid. The second
* word holds the UART physical address.
*/
#define TEGRA_IRAM_DEBUG_UART_OFFSET SZ_1K
#define TEGRA_IRAM_DEBUG_UART_SIZE 8
#define TEGRA_IRAM_DEBUG_UART_COOKIE 0x55415254
#endif

View File

@ -2,10 +2,14 @@
* arch/arm/mach-tegra/include/mach/uncompress.h
*
* Copyright (C) 2010 Google, Inc.
* Copyright (C) 2011 Google, Inc.
* Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
*
* Author:
* Colin Cross <ccross@google.com>
* Erik Gilling <konkers@google.com>
* Doug Anderson <dianders@chromium.org>
* Stephen Warren <swarren@nvidia.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@ -25,36 +29,130 @@
#include <linux/serial_reg.h>
#include <mach/iomap.h>
#include <mach/irammap.h>
#define BIT(x) (1 << (x))
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define DEBUG_UART_SHIFT 2
volatile u8 *uart;
static void putc(int c)
{
volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
int shift = 2;
if (uart == NULL)
return;
while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
while (!(uart[UART_LSR << DEBUG_UART_SHIFT] & UART_LSR_THRE))
barrier();
uart[UART_TX << shift] = c;
uart[UART_TX << DEBUG_UART_SHIFT] = c;
}
static inline void flush(void)
{
}
static inline void save_uart_address(void)
{
u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET);
if (uart) {
buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE;
buf[1] = (u32)uart;
} else
buf[0] = 0;
}
/*
* Setup before decompression. This is where we do UART selection for
* earlyprintk and init the uart_base register.
*/
static inline void arch_decomp_setup(void)
{
volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
int shift = 2;
static const struct {
u32 base;
u32 reset_reg;
u32 clock_reg;
u32 bit;
} uarts[] = {
{
TEGRA_UARTA_BASE,
TEGRA_CLK_RESET_BASE + 0x04,
TEGRA_CLK_RESET_BASE + 0x10,
6,
},
{
TEGRA_UARTB_BASE,
TEGRA_CLK_RESET_BASE + 0x04,
TEGRA_CLK_RESET_BASE + 0x10,
7,
},
{
TEGRA_UARTC_BASE,
TEGRA_CLK_RESET_BASE + 0x08,
TEGRA_CLK_RESET_BASE + 0x14,
23,
},
{
TEGRA_UARTD_BASE,
TEGRA_CLK_RESET_BASE + 0x0c,
TEGRA_CLK_RESET_BASE + 0x18,
1,
},
{
TEGRA_UARTE_BASE,
TEGRA_CLK_RESET_BASE + 0x0c,
TEGRA_CLK_RESET_BASE + 0x18,
2,
},
};
int i;
volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
u32 chip, div;
/*
* Look for the first UART that:
* a) Is not in reset.
* b) Is clocked.
* c) Has a 'D' in the scratchpad register.
*
* Note that on Tegra30, the first two conditions are required, since
* if not true, accesses to the UART scratch register will hang.
* Tegra20 doesn't have this issue.
*
* The intent is that the bootloader will tell the kernel which UART
* to use by setting up those conditions. If nothing found, we'll fall
* back to what's specified in TEGRA_DEBUG_UART_BASE.
*/
for (i = 0; i < ARRAY_SIZE(uarts); i++) {
if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
continue;
if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
continue;
uart = (volatile u8 *)uarts[i].base;
if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
continue;
break;
}
if (i == ARRAY_SIZE(uarts))
uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
save_uart_address();
if (uart == NULL)
return;
uart[UART_LCR << shift] |= UART_LCR_DLAB;
uart[UART_DLL << shift] = 0x75;
uart[UART_DLM << shift] = 0x0;
uart[UART_LCR << shift] = 3;
chip = (apb_misc[0x804 / 4] >> 8) & 0xff;
if (chip == 0x20)
div = 0x0075;
else
div = 0x00dd;
uart[UART_LCR << DEBUG_UART_SHIFT] |= UART_LCR_DLAB;
uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff;
uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8;
uart[UART_LCR << DEBUG_UART_SHIFT] = 3;
}
static inline void arch_decomp_wdog(void)

76
arch/arm/mach-tegra/pmc.c Normal file
View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/of.h>
#include <mach/iomap.h>
#define PMC_CTRL 0x0
#define PMC_CTRL_INTR_LOW (1 << 17)
static inline u32 tegra_pmc_readl(u32 reg)
{
return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg));
}
static inline void tegra_pmc_writel(u32 val, u32 reg)
{
writel(val, IO_ADDRESS(TEGRA_PMC_BASE + reg));
}
#ifdef CONFIG_OF
static const struct of_device_id matches[] __initconst = {
{ .compatible = "nvidia,tegra20-pmc" },
{ }
};
#endif
void __init tegra_pmc_init(void)
{
/*
* For now, Harmony is the only board that uses the PMC, and it wants
* the signal inverted. Seaboard would too if it used the PMC.
* Hopefully by the time other boards want to use the PMC, everything
* will be device-tree, or they also want it inverted.
*/
bool invert_interrupt = true;
u32 val;
#ifdef CONFIG_OF
if (of_have_populated_dt()) {
struct device_node *np;
invert_interrupt = false;
np = of_find_matching_node(NULL, matches);
if (np) {
if (of_find_property(np, "nvidia,invert-interrupt",
NULL))
invert_interrupt = true;
}
}
#endif
val = tegra_pmc_readl(PMC_CTRL);
if (invert_interrupt)
val |= PMC_CTRL_INTR_LOW;
else
val &= ~PMC_CTRL_INTR_LOW;
tegra_pmc_writel(val, PMC_CTRL);
}

23
arch/arm/mach-tegra/pmc.h Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __MACH_TEGRA_PMC_H
#define __MACH_TEGRA_PMC_H
void tegra_pmc_init(void);
#endif

View File

@ -720,7 +720,7 @@ static void tegra2_pllx_clk_init(struct clk *c)
{
tegra2_pll_clk_init(c);
if (tegra_sku_id() == 7)
if (tegra_sku_id == 7)
c->max_rate = 750000000;
}

View File

@ -16,14 +16,19 @@
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_emc.h>
#include <mach/iomap.h>
#include "tegra2_emc.h"
#include "fuse.h"
#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
static bool emc_enable = true;
@ -32,18 +37,17 @@ static bool emc_enable;
#endif
module_param(emc_enable, bool, 0644);
static void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE);
static const struct tegra_emc_table *tegra_emc_table;
static int tegra_emc_table_size;
static struct platform_device *emc_pdev;
static void __iomem *emc_regbase;
static inline void emc_writel(u32 val, unsigned long addr)
{
writel(val, emc + addr);
writel(val, emc_regbase + addr);
}
static inline u32 emc_readl(unsigned long addr)
{
return readl(emc + addr);
return readl(emc_regbase + addr);
}
static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
@ -98,15 +102,15 @@ static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
/* Select the closest EMC rate that is higher than the requested rate */
long tegra_emc_round_rate(unsigned long rate)
{
struct tegra_emc_pdata *pdata;
int i;
int best = -1;
unsigned long distance = ULONG_MAX;
if (!tegra_emc_table)
if (!emc_pdev)
return -EINVAL;
if (!emc_enable)
return -EINVAL;
pdata = emc_pdev->dev.platform_data;
pr_debug("%s: %lu\n", __func__, rate);
@ -116,10 +120,10 @@ long tegra_emc_round_rate(unsigned long rate)
*/
rate = rate / 2 / 1000;
for (i = 0; i < tegra_emc_table_size; i++) {
if (tegra_emc_table[i].rate >= rate &&
(tegra_emc_table[i].rate - rate) < distance) {
distance = tegra_emc_table[i].rate - rate;
for (i = 0; i < pdata->num_tables; i++) {
if (pdata->tables[i].rate >= rate &&
(pdata->tables[i].rate - rate) < distance) {
distance = pdata->tables[i].rate - rate;
best = i;
}
}
@ -127,9 +131,9 @@ long tegra_emc_round_rate(unsigned long rate)
if (best < 0)
return -EINVAL;
pr_debug("%s: using %lu\n", __func__, tegra_emc_table[best].rate);
pr_debug("%s: using %lu\n", __func__, pdata->tables[best].rate);
return tegra_emc_table[best].rate * 2 * 1000;
return pdata->tables[best].rate * 2 * 1000;
}
/*
@ -142,37 +146,211 @@ long tegra_emc_round_rate(unsigned long rate)
*/
int tegra_emc_set_rate(unsigned long rate)
{
struct tegra_emc_pdata *pdata;
int i;
int j;
if (!tegra_emc_table)
if (!emc_pdev)
return -EINVAL;
pdata = emc_pdev->dev.platform_data;
/*
* The EMC clock rate is twice the bus rate, and the bus rate is
* measured in kHz
*/
rate = rate / 2 / 1000;
for (i = 0; i < tegra_emc_table_size; i++)
if (tegra_emc_table[i].rate == rate)
for (i = 0; i < pdata->num_tables; i++)
if (pdata->tables[i].rate == rate)
break;
if (i >= tegra_emc_table_size)
if (i >= pdata->num_tables)
return -EINVAL;
pr_debug("%s: setting to %lu\n", __func__, rate);
for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]);
emc_writel(pdata->tables[i].regs[j], emc_reg_addr[j]);
emc_readl(tegra_emc_table[i].regs[TEGRA_EMC_NUM_REGS - 1]);
emc_readl(pdata->tables[i].regs[TEGRA_EMC_NUM_REGS - 1]);
return 0;
}
void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
#ifdef CONFIG_OF
static struct device_node *tegra_emc_ramcode_devnode(struct device_node *np)
{
tegra_emc_table = table;
tegra_emc_table_size = table_size;
struct device_node *iter;
u32 reg;
for_each_child_of_node(np, iter) {
if (of_property_read_u32(np, "nvidia,ram-code", &reg))
continue;
if (reg == tegra_bct_strapping)
return of_node_get(iter);
}
return NULL;
}
static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *tnp, *iter;
struct tegra_emc_pdata *pdata;
int ret, i, num_tables;
if (!np)
return NULL;
if (of_find_property(np, "nvidia,use-ram-code", NULL)) {
tnp = tegra_emc_ramcode_devnode(np);
if (!tnp)
dev_warn(&pdev->dev,
"can't find emc table for ram-code 0x%02x\n",
tegra_bct_strapping);
} else
tnp = of_node_get(np);
if (!tnp)
return NULL;
num_tables = 0;
for_each_child_of_node(tnp, iter)
if (of_device_is_compatible(iter, "nvidia,tegra20-emc-table"))
num_tables++;
if (!num_tables) {
pdata = NULL;
goto out;
}
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
pdata->tables = devm_kzalloc(&pdev->dev,
sizeof(*pdata->tables) * num_tables,
GFP_KERNEL);
i = 0;
for_each_child_of_node(tnp, iter) {
u32 prop;
ret = of_property_read_u32(iter, "clock-frequency", &prop);
if (ret) {
dev_err(&pdev->dev, "no clock-frequency in %s\n",
iter->full_name);
continue;
}
pdata->tables[i].rate = prop;
ret = of_property_read_u32_array(iter, "nvidia,emc-registers",
pdata->tables[i].regs,
TEGRA_EMC_NUM_REGS);
if (ret) {
dev_err(&pdev->dev,
"malformed emc-registers property in %s\n",
iter->full_name);
continue;
}
i++;
}
pdata->num_tables = i;
out:
of_node_put(tnp);
return pdata;
}
#else
static struct tegra_emc_pdata *tegra_emc_dt_parse_pdata(
struct platform_device *pdev)
{
return NULL;
}
#endif
static struct tegra_emc_pdata __devinit *tegra_emc_fill_pdata(struct platform_device *pdev)
{
struct clk *c = clk_get_sys(NULL, "emc");
struct tegra_emc_pdata *pdata;
unsigned long khz;
int i;
WARN_ON(pdev->dev.platform_data);
BUG_ON(IS_ERR_OR_NULL(c));
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
pdata->tables = devm_kzalloc(&pdev->dev, sizeof(*pdata->tables),
GFP_KERNEL);
pdata->tables[0].rate = clk_get_rate(c) / 2 / 1000;
for (i = 0; i < TEGRA_EMC_NUM_REGS; i++)
pdata->tables[0].regs[i] = emc_readl(emc_reg_addr[i]);
pdata->num_tables = 1;
khz = pdata->tables[0].rate;
dev_info(&pdev->dev, "no tables provided, using %ld kHz emc, "
"%ld kHz mem\n", khz * 2, khz);
return pdata;
}
static int __devinit tegra_emc_probe(struct platform_device *pdev)
{
struct tegra_emc_pdata *pdata;
struct resource *res;
if (!emc_enable) {
dev_err(&pdev->dev, "disabled per module parameter\n");
return -ENODEV;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "missing register base\n");
return -ENOMEM;
}
emc_regbase = devm_request_and_ioremap(&pdev->dev, res);
if (!emc_regbase) {
dev_err(&pdev->dev, "failed to remap registers\n");
return -ENOMEM;
}
pdata = pdev->dev.platform_data;
if (!pdata)
pdata = tegra_emc_dt_parse_pdata(pdev);
if (!pdata)
pdata = tegra_emc_fill_pdata(pdev);
pdev->dev.platform_data = pdata;
emc_pdev = pdev;
return 0;
}
static struct of_device_id tegra_emc_of_match[] __devinitdata = {
{ .compatible = "nvidia,tegra20-emc", },
{ },
};
static struct platform_driver tegra_emc_driver = {
.driver = {
.name = "tegra-emc",
.owner = THIS_MODULE,
.of_match_table = tegra_emc_of_match,
},
.probe = tegra_emc_probe,
};
static int __init tegra_emc_init(void)
{
return platform_driver_register(&tegra_emc_driver);
}
device_initcall(tegra_emc_init);

View File

@ -15,13 +15,10 @@
*
*/
#define TEGRA_EMC_NUM_REGS 46
struct tegra_emc_table {
unsigned long rate;
u32 regs[TEGRA_EMC_NUM_REGS];
};
#ifndef __MACH_TEGRA_TEGRA2_EMC_H_
#define __MACH_TEGRA_TEGRA2_EMC_H
int tegra_emc_set_rate(unsigned long rate);
long tegra_emc_round_rate(unsigned long rate);
void tegra_init_emc(const struct tegra_emc_table *table, int table_size);
#endif

View File

@ -60,9 +60,9 @@ static int imx_sata_init(struct device *dev, void __iomem *addr)
dev_err(dev, "no sata clock.\n");
return PTR_ERR(sata_clk);
}
ret = clk_enable(sata_clk);
ret = clk_prepare_enable(sata_clk);
if (ret) {
dev_err(dev, "can't enable sata clock.\n");
dev_err(dev, "can't prepare/enable sata clock.\n");
goto put_sata_clk;
}
@ -73,9 +73,9 @@ static int imx_sata_init(struct device *dev, void __iomem *addr)
ret = PTR_ERR(sata_ref_clk);
goto release_sata_clk;
}
ret = clk_enable(sata_ref_clk);
ret = clk_prepare_enable(sata_ref_clk);
if (ret) {
dev_err(dev, "can't enable sata ref clock.\n");
dev_err(dev, "can't prepare/enable sata ref clock.\n");
goto put_sata_ref_clk;
}
@ -104,11 +104,11 @@ static int imx_sata_init(struct device *dev, void __iomem *addr)
return 0;
release_sata_ref_clk:
clk_disable(sata_ref_clk);
clk_disable_unprepare(sata_ref_clk);
put_sata_ref_clk:
clk_put(sata_ref_clk);
release_sata_clk:
clk_disable(sata_clk);
clk_disable_unprepare(sata_clk);
put_sata_clk:
clk_put(sata_clk);
@ -117,10 +117,10 @@ put_sata_clk:
static void imx_sata_exit(struct device *dev)
{
clk_disable(sata_ref_clk);
clk_disable_unprepare(sata_ref_clk);
clk_put(sata_ref_clk);
clk_disable(sata_clk);
clk_disable_unprepare(sata_clk);
clk_put(sata_clk);
}

View File

@ -203,7 +203,7 @@ static int __init epit_clockevent_init(struct clk *timer_clk)
void __init epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
{
clk_enable(timer_clk);
clk_prepare_enable(timer_clk);
timer_base = base;

View File

@ -1,33 +0,0 @@
/*
* Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__
#define __ASM_ARCH_MXC_BOARD_MX31ADS_H__
#include <mach/hardware.h>
/*
* These symbols are used by drivers/net/cs89x0.c.
* This is ugly as hell, but we have to provide them until
* someone fixed the driver.
*/
/* Base address of PBC controller */
#define PBC_BASE_ADDRESS MX31_CS4_BASE_ADDR_VIRT
/* Offsets for the PBC Controller register */
/* Ethernet Controller IO base address */
#define PBC_CS8900A_IOBASE 0x020000
#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START)
#define EXPIO_INT_ENET_INT (MXC_EXP_IO_BASE + 8)
#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */

View File

@ -24,7 +24,7 @@
#define UART_PADDR MX51_UART1_BASE_ADDR
#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
#define UART_PADDR MX53_UART1_BASE_ADDR
#elif defined (CONFIG_DEBUG_IMX6Q_UART)
#elif defined (CONFIG_DEBUG_IMX6Q_UART4)
#define UART_PADDR MX6Q_UART4_BASE_ADDR
#endif

View File

@ -60,8 +60,7 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
{
return !strcmp(dev_name(chan->device->dev), "imx31-sdma") ||
!strcmp(dev_name(chan->device->dev), "imx35-sdma") ||
return strstr(dev_name(chan->device->dev), "sdma") ||
!strcmp(dev_name(chan->device->dev), "imx-dma");
}

View File

@ -132,7 +132,7 @@ int pwm_enable(struct pwm_device *pwm)
int rc = 0;
if (!pwm->clk_enabled) {
rc = clk_enable(pwm->clk);
rc = clk_prepare_enable(pwm->clk);
if (!rc)
pwm->clk_enabled = 1;
}
@ -145,7 +145,7 @@ void pwm_disable(struct pwm_device *pwm)
writel(0, pwm->mmio_base + MX3_PWMCR);
if (pwm->clk_enabled) {
clk_disable(pwm->clk);
clk_disable_unprepare(pwm->clk);
pwm->clk_enabled = 0;
}
}

View File

@ -48,7 +48,7 @@ void mxc_restart(char mode, const char *cmd)
clk = clk_get_sys("imx2-wdt.0", NULL);
if (!IS_ERR(clk))
clk_enable(clk);
clk_prepare_enable(clk);
wcr_enable = (1 << 2);
}

View File

@ -283,7 +283,7 @@ void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
{
uint32_t tctl_val;
clk_enable(timer_clk);
clk_prepare_enable(timer_clk);
timer_base = base;

View File

@ -484,7 +484,6 @@ struct omap_hwmod_class {
* @main_clk: main clock: OMAP clock name
* @_clk: pointer to the main struct clk (filled in at runtime)
* @opt_clks: other device clocks that drivers can request (0..*)
* @vdd_name: voltage domain name
* @voltdm: pointer to voltage domain (filled in at runtime)
* @masters: ptr to array of OCP ifs that this hwmod can initiate on
* @slaves: ptr to array of OCP ifs that this hwmod can respond on
@ -528,7 +527,6 @@ struct omap_hwmod {
struct omap_hwmod_opt_clk *opt_clks;
char *clkdm_name;
struct clockdomain *clkdm;
char *vdd_name;
struct omap_hwmod_ocp_if **masters; /* connect to *_IA */
struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */
void *dev_attr;

View File

@ -82,6 +82,22 @@ enum dma_ch {
DMACH_SLIMBUS4_TX,
DMACH_SLIMBUS5_RX,
DMACH_SLIMBUS5_TX,
DMACH_MIPI_HSI0,
DMACH_MIPI_HSI1,
DMACH_MIPI_HSI2,
DMACH_MIPI_HSI3,
DMACH_MIPI_HSI4,
DMACH_MIPI_HSI5,
DMACH_MIPI_HSI6,
DMACH_MIPI_HSI7,
DMACH_MTOM_0,
DMACH_MTOM_1,
DMACH_MTOM_2,
DMACH_MTOM_3,
DMACH_MTOM_4,
DMACH_MTOM_5,
DMACH_MTOM_6,
DMACH_MTOM_7,
/* END Marker, also used to denote a reserved channel */
DMACH_MAX,
};

View File

@ -18,51 +18,54 @@
#define S3C2410_INTP_ALM (1 << 1)
#define S3C2410_INTP_TIC (1 << 0)
#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
#define S3C2410_RTCCON_RTCEN (1<<0)
#define S3C2410_RTCCON_CLKSEL (1<<1)
#define S3C2410_RTCCON_CNTSEL (1<<2)
#define S3C2410_RTCCON_CLKRST (1<<3)
#define S3C64XX_RTCCON_TICEN (1<<8)
#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
#define S3C2410_RTCCON_RTCEN (1 << 0)
#define S3C2410_RTCCON_CNTSEL (1 << 2)
#define S3C2410_RTCCON_CLKRST (1 << 3)
#define S3C2443_RTCCON_TICSEL (1 << 4)
#define S3C64XX_RTCCON_TICEN (1 << 8)
#define S3C64XX_RTCCON_TICMSK (0xF<<7)
#define S3C64XX_RTCCON_TICSHT (7)
#define S3C2410_TICNT S3C2410_RTCREG(0x44)
#define S3C2410_TICNT_ENABLE (1 << 7)
#define S3C2410_TICNT S3C2410_RTCREG(0x44)
#define S3C2410_TICNT_ENABLE (1<<7)
/* S3C2443: tick count is 15 bit wide
* TICNT[6:0] contains upper 7 bits
* TICNT1[7:0] contains lower 8 bits
*/
#define S3C2443_TICNT_PART(x) ((x & 0x7f00) >> 8)
#define S3C2443_TICNT1 S3C2410_RTCREG(0x4C)
#define S3C2443_TICNT1_PART(x) (x & 0xff)
#define S3C2410_RTCALM S3C2410_RTCREG(0x50)
#define S3C2410_RTCALM_ALMEN (1<<6)
#define S3C2410_RTCALM_YEAREN (1<<5)
#define S3C2410_RTCALM_MONEN (1<<4)
#define S3C2410_RTCALM_DAYEN (1<<3)
#define S3C2410_RTCALM_HOUREN (1<<2)
#define S3C2410_RTCALM_MINEN (1<<1)
#define S3C2410_RTCALM_SECEN (1<<0)
/* S3C2416: tick count is 32 bit wide
* TICNT[6:0] contains bits [14:8]
* TICNT1[7:0] contains lower 8 bits
* TICNT2[16:0] contains upper 17 bits
*/
#define S3C2416_TICNT2 S3C2410_RTCREG(0x48)
#define S3C2416_TICNT2_PART(x) ((x & 0xffff8000) >> 15)
#define S3C2410_RTCALM_ALL \
S3C2410_RTCALM_ALMEN | S3C2410_RTCALM_YEAREN | S3C2410_RTCALM_MONEN |\
S3C2410_RTCALM_DAYEN | S3C2410_RTCALM_HOUREN | S3C2410_RTCALM_MINEN |\
S3C2410_RTCALM_SECEN
#define S3C2410_RTCALM S3C2410_RTCREG(0x50)
#define S3C2410_RTCALM_ALMEN (1 << 6)
#define S3C2410_RTCALM_YEAREN (1 << 5)
#define S3C2410_RTCALM_MONEN (1 << 4)
#define S3C2410_RTCALM_DAYEN (1 << 3)
#define S3C2410_RTCALM_HOUREN (1 << 2)
#define S3C2410_RTCALM_MINEN (1 << 1)
#define S3C2410_RTCALM_SECEN (1 << 0)
#define S3C2410_ALMSEC S3C2410_RTCREG(0x54)
#define S3C2410_ALMMIN S3C2410_RTCREG(0x58)
#define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c)
#define S3C2410_ALMSEC S3C2410_RTCREG(0x54)
#define S3C2410_ALMMIN S3C2410_RTCREG(0x58)
#define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c)
#define S3C2410_ALMDATE S3C2410_RTCREG(0x60)
#define S3C2410_ALMMON S3C2410_RTCREG(0x64)
#define S3C2410_ALMYEAR S3C2410_RTCREG(0x68)
#define S3C2410_RTCRST S3C2410_RTCREG(0x6c)
#define S3C2410_RTCSEC S3C2410_RTCREG(0x70)
#define S3C2410_RTCMIN S3C2410_RTCREG(0x74)
#define S3C2410_RTCHOUR S3C2410_RTCREG(0x78)
#define S3C2410_RTCDATE S3C2410_RTCREG(0x7c)
#define S3C2410_RTCDAY S3C2410_RTCREG(0x80)
#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
#define S3C2410_ALMDATE S3C2410_RTCREG(0x60)
#define S3C2410_ALMMON S3C2410_RTCREG(0x64)
#define S3C2410_ALMYEAR S3C2410_RTCREG(0x68)
#define S3C2410_RTCSEC S3C2410_RTCREG(0x70)
#define S3C2410_RTCMIN S3C2410_RTCREG(0x74)
#define S3C2410_RTCHOUR S3C2410_RTCREG(0x78)
#define S3C2410_RTCDATE S3C2410_RTCREG(0x7c)
#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
#endif /* __ASM_ARCH_REGS_RTC_H */

View File

@ -0,0 +1,27 @@
/* linux/arch/arm/plat-samsung/include/plat/rtc-core.h
*
* Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de>
*
* Samsung RTC Controller core functions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_PLAT_RTC_CORE_H
#define __ASM_PLAT_RTC_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_rtc_setname(char *name)
{
#if defined(CONFIG_SAMSUNG_DEV_RTC) || defined(CONFIG_PLAT_S3C24XX)
s3c_device_rtc.name = name;
#endif
}
#endif /* __ASM_PLAT_RTC_CORE_H */

View File

@ -40,6 +40,7 @@ enum clk_types {
* struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
* @max_width: The maximum number of data bits supported.
* @host_caps: Standard MMC host capabilities bit field.
* @host_caps2: The second standard MMC host capabilities bit field.
* @cd_type: Type of Card Detection method (see cd_types enum above)
* @clk_type: Type of clock divider method (see clk_types enum above)
* @ext_cd_init: Initialize external card detect subsystem. Called on
@ -63,6 +64,7 @@ enum clk_types {
struct s3c_sdhci_platdata {
unsigned int max_width;
unsigned int host_caps;
unsigned int host_caps2;
unsigned int pm_caps;
enum cd_types cd_type;
enum clk_types clk_type;

Some files were not shown because too many files have changed in this diff Show More