* [PATCH 2/3] mmc: Add OF bindings support for mmc host controller capabilities
From: Thomas Abraham @ 2011-10-11 18:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <74CDBE0F657A3D45AFBB94109FB122FF173BE19AAE@HQMAIL01.nvidia.com>
On 11 October 2011 21:59, Stephen Warren <swarren@nvidia.com> wrote:
> Thomas Abraham wrote at Sunday, October 09, 2011 12:58 AM:
>> On 5 October 2011 21:25, Stephen Warren <swarren@nvidia.com> wrote:
>> > Thomas Abraham wrote at Wednesday, October 05, 2011 8:28 AM:
>> >> On 5 October 2011 18:59, Rob Herring <robherring2@gmail.com> wrote:
>> >> > On 10/05/2011 05:13 AM, Thomas Abraham wrote:
>> >> >> Device nodes representing sd/mmc controllers in a device tree would include
>> >> >> mmc host controller capabilities. Add support for parsing of mmc host
>> >> >> controller capabilities included in device nodes.
>> > ...
>> >> >> +- linux,mmc_cap_4_bit_data - host can do 4 bit transfers
>> >> >> +- linux,mmc_cap_mmc_highspeed - host can do MMC high-speed timing
>> >> >> +- linux,mmc_cap_sd_highspeed - host can do SD high-speed timing
>> >> >> +- linux,mmc_cap_needs_poll - host needs polling for card detection
>> >> >> +- linux,mmc_cap_8_bit_data - host can do 8 bit transfer
>> >> >
>> >> > "sdhci,1-bit-only" already exists as a binding. Perhaps add
>> >> > "sdhci,4-bit-only". No property then means can do 8-bit.
>> >>
>> >> Ok. But that would remain just as sdhci host controller capability and
>> >> will not be applicable to other types of host controllers.
>> >
>> > Just as an FYI, NVIDIA's SDHCI controller bindings use property
>> > "support-8bit" to indicate 8-bit support. A similar property could be
>> > used for 4-bit support too.
>>
>> In this case, the binding would be applicable only to nVidia's SDHCI
>> controller.
>
> Sure, this is the case right now. And I thought I'd copied this property
> name from some other driver, but it looks like I'm mistaken.
>
>> And this binding would select MMC_CAP_8_BIT_DATA in the
>> sdhci-tegra driver. There are sdhci drivers that can accept host
>> capabilities via platform data.
>>
>> The MMC_CAP_XXX macros in linux/mmc/host.h file are usuable across
>> host controllers and some of them are supplied as platform data for
>> non-device tree platforms.
>>
>> So, bindings for MMC_CAP_XXX macros can be defined which any host
>> controller supporting device tree could use. Host controllers could
>> use the mmc_of_parse_host_caps() helper function (listed in this
>> patch) to parse all the bindings for MMC_CAP_XXX ?available in the
>> device node.
>>
>> I would like to retain this patch in this series but if there is a
>> definite no, then I will drop it. Please let me know your opinion.
>
> I was simply pointing out that there are already some properties in this
> area. It'd be nice if we could unify everything on a single style; either
> expanding the existing "sdhci,1-bit-only" style that Rob mentioned, or
> expanding the "support-8bit" style that Tegra currently uses, rather than
> adding a third way of indicating this. Still, given the early state of
> DT on Tegra, I'd be happy migrating Tegra to whatever single unified
> approach is chosen, so don't take my comments as nak'ing your patch or
> anything like that.
Ok.
The sdhci bus width binding is an example that can be extended as you
have suggested. If done this way, the sdhci bus width bindings would
be converted by the driver to either of MMC_CAP_[4/8]_BIT_DATA
capability.
But there are other MMC_CAP_XXX values as well which the host
controller driver needs to report to the upper mmc core layer. Some of
these capabilities are determined by reading caps register of the host
controller and converting them to equivalent MMC_CAP_XXX flags. But
some of them are board dependent such as
MMC_CAP_NEEDS_POLL,
MMC_CAP_DISABLE,
MMC_CAP_NONREMOVABLE,
MMC_CAP_POWER_OFF_CARD and others.
These flags which are tied to the characteristics of the board is
usually supplied using platform data. The driver picks up these from
platform data, adds its own set of CAP's and reports to the upper
layer.
When we do not have platform data (as in the case of dt), there could
be two options to bind these CAP's. Either define custom bindings for
these and then translate them in each host controller driver using
them or provide direct bindings for MMC_CAP_xxx with a common function
to parse them. I tend towards direct bindings for MMC_CAP_XXX because
it can be used by any type of mmc/sd host controller and not just
sdhci controller and provides common binding for all host controllers.
Thanks for your comments.
Regards,
Thomas.
>
> --
> nvpublic
>
>
^ permalink raw reply
* [Linaro-mm-sig] [PATCH 1/2] ARM: initial proof-of-concept IOMMU mapper for DMA-mapping
From: Krishna Reddy @ 2011-10-11 18:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <00b101cc87ee$8976c410$9c644c30$%szyprowski@samsung.com>
Marek,
>It looks that You have simplified arm_iommu_map_sg() function too much.
>The main advantage of the iommu is to map scattered memory pages into
>contiguous dma address space. DMA-mapping is allowed to merge consecutive
>entries in the scatter list if hardware supports that.
>http://article.gmane.org/gmane.linux.kernel/1128416
I would update arm_iommu_map_sg() back to coalesce the sg list.
>I'm not sure if mmc drivers are aware of coalescing the SG entries together.
>If not the code must be updated to use dma_sg_len() and the dma entries
>number returned from dma_map_sg() call.
MMC drivers seem to be aware of coalescing the SG entries together as they are using dma_sg_len().
Let me test and update the patch.
--
nvpublic
^ permalink raw reply
* [PATCH v6 10/16] OMAP2+: UART: Modify omap_uart_can_sleep function
From: Kevin Hilman @ 2011-10-11 18:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317380561-661-1-git-send-email-govindraj.raja@ti.com>
"Govindraj.R" <govindraj.raja@ti.com> writes:
> Modify the omap_uart_can_sleep function to check uart is active
> or not to be used by pm code to enter low power states.
Doesn't the driver now control when the UART clocks are gated (using
runtime PM autosuspend)?
IMO, this check should be completely removed and the driver should
be managing this with the autosuspend timeout.
> Removing this check can cause console response little sluggish.
Sluggish in what way?
If the driver is runtime suspended, it should only be sluggish for the
first character. After that, the autosuspend timeout should prevent it
from feeling sluggish.
> However no characters will be lost until uart clocks are gated
> and woken up using rx-pad. UART interface clocks can be auto gated
> this can make response on uart slower. This behaviour was observed
> only on some of OMAP3 boards(beagleboard xm rev c).
>
> Reported-by: Tero Kristo <t-kristo@ti.com>
> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
> ---
> arch/arm/mach-omap2/serial.c | 21 +++++++++------------
> 1 files changed, 9 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
> index 6725caf..ccf3550 100644
> --- a/arch/arm/mach-omap2/serial.c
> +++ b/arch/arm/mach-omap2/serial.c
> @@ -156,23 +156,20 @@ static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
>
> int omap_uart_can_sleep(void)
> {
> - struct omap_uart_state *uart;
> - int can_sleep = 1;
> -
> - list_for_each_entry(uart, &uart_list, node) {
> - if (!uart->clocked)
> - continue;
> + struct omap_hwmod *oh;
> + u8 i, ret = true;
>
> - if (!uart->can_sleep) {
> - can_sleep = 0;
> + for (i = 0; i < num_uarts; i++) {
> + oh = omap_uart_hwmod_lookup(i);
This is a heavy operation to add for *every* entry into idle.
> + if (!oh)
> continue;
> - }
>
> - /* This UART can now safely sleep. */
> - omap_uart_allow_sleep(uart);
> + if (oh->od && oh->od->pdev &&
> + !pm_runtime_suspended(&oh->od->pdev->dev))
> + return false;
> }
>
> - return can_sleep;
> + return ret;
> }
>
> #ifdef CONFIG_OMAP_MUX
Kevin
^ permalink raw reply
* [RFC PATCH] tty/serial: RS485 bindings for device tree
From: Arnd Bergmann @ 2011-10-11 18:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4E947CA6.9010703@atmel.com>
On Tuesday 11 October 2011 19:28:06 Nicolas Ferre wrote:
>
> > +Optional properties:
> > +- linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485
> > + feature at boot time. It can be disabled later with proper ioctl.
>
> +- linux,rs485-rx-during-tx: empty property that enable the receiving of data
> + even whilst sending data.
This does not sound too linux specific. If it's a hardware property, don't
use the 'linux,' prefix and just make it 'rs484-full-duplex' or such.
Arnd
^ permalink raw reply
* [GIT PULL] DEBUG_LL platform updates for 3.2
From: Will Deacon @ 2011-10-11 18:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111011150915.GE23188@mudshark.cambridge.arm.com>
Just to follow up on this...
On Tue, Oct 11, 2011 at 04:09:15PM +0100, Will Deacon wrote:
> For the cpu-mapping, I depend on:
>
> ARM: 7011/1: Add ARM cpu topology definition
> ARM: 7060/1: smp: populate logical CPU mapping during boot
> ARM: 7061/1: gic: convert logical CPU numbers into physical numbers
>
> which I can only see in Russell's for-next branch.
>
> For the debug-ll stuff, I depend on:
>
> ARM: 7072/1: debug: use kconfig choice for selecting DEBUG_LL UART
>
> and conflict with:
>
> ARM: 7097/1: debug: Move DEBUG_ICEDCC into the DEBUG_LL choice
> ARM: 7096/1: debug: Add UART1 config choices
> ARM: 7116/1: debug: provide dummy default option for DEBUG_LL UART choice
> ARM: 7073/1: debug: augment DEBUG_LL Kconfig help to clarify behaviour
I've stuck a debug-ll branch and a cpu-mapping branch here:
git://github.com/wdeacon/linux-wd.git
(I finally gave up with my old broken git server!)
These branches are based against -rc9 and I've cherry-picked the
dependencies from Russell's for-next branch. I'm not sure that's good for
anything, but it at least helps to show what's already in Russell's tree
and what's currently outstanding.
Will
^ permalink raw reply
* [PATCH v6 12/16] OMAP2+: UART: Allow UART parameters to be configured from board file.
From: Kevin Hilman @ 2011-10-11 18:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317380561-661-3-git-send-email-govindraj.raja@ti.com>
"Govindraj.R" <govindraj.raja@ti.com> writes:
> From: Deepak K <deepak.k@ti.com>
>
> The following UART parameters are defined within the UART driver:
>
> 1). Whether the UART uses DMA (dma_enabled), by default set to 0
> 2). The size of dma buffer (set to 4096 bytes)
> 3). The time after which the dma should stop if no more data is received.
> 4). The auto suspend delay that will be passed for pm_runtime_autosuspend
> where uart will be disabled after timeout
>
> Different UARTs may be used for different purpose such as the console,
> for interfacing bluetooth chip, for interfacing to a modem chip, etc.
> Therefore, it is necessary to be able to customize the above settings
> for a given board on a per UART basis.
>
> This change allows these parameters to be configured from the board file
> and allows the parameters to be configured for each UART independently.
>
> If a board does not define its own custom parameters for the UARTs, then
> use the default parameters in the structure "omap_serial_default_info".
> The default parameters are defined to be the same as the current settings
> in the UART driver to avoid breaking the UART for any cuurnelty supported
> boards. By default, make all boards use the default UART parameters.
>
> Signed-off-by: Deepak K <deepak.k@ti.com>
> Signed-off-by: Jon Hunter <jon-hunter@ti.com>
> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
A couple minor comments below...
> ---
> This patch is derived and reworked from a custom 2.6.35 kernel
> Available here:
> http://git.omapzoom.org/?p=kernel/omap.git;
> a=commitdiff;h=584ef316542f77312be7ba96a0f3013c8f64852b;
> hp=7233a76cb362c0fc603f773274159adff91d3513
>
> arch/arm/mach-omap2/board-n8x0.c | 6 +-
> arch/arm/mach-omap2/serial.c | 56 ++++++++++++++++++++----
> arch/arm/plat-omap/include/plat/omap-serial.h | 7 ++-
> arch/arm/plat-omap/include/plat/serial.h | 5 ++-
> drivers/tty/serial/omap-serial.c | 8 +--
> 5 files changed, 61 insertions(+), 21 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
> index e11f0c5..3408726 100644
> --- a/arch/arm/mach-omap2/board-n8x0.c
> +++ b/arch/arm/mach-omap2/board-n8x0.c
> @@ -656,15 +656,15 @@ static inline void board_serial_init(void)
> bdata.pads_cnt = 0;
>
> bdata.id = 0;
> - omap_serial_init_port(&bdata);
> + omap_serial_init_port(&bdata, NULL);
>
> bdata.id = 1;
> - omap_serial_init_port(&bdata);
> + omap_serial_init_port(&bdata, NULL);
>
> bdata.id = 2;
> bdata.pads = serial2_pads;
> bdata.pads_cnt = ARRAY_SIZE(serial2_pads);
> - omap_serial_init_port(&bdata);
> + omap_serial_init_port(&bdata, NULL);
> }
>
> #else
> diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
> index 0731575..78f7051 100644
> --- a/arch/arm/mach-omap2/serial.c
> +++ b/arch/arm/mach-omap2/serial.c
> @@ -43,17 +43,29 @@
> #include "mux.h"
>
> /*
> - * NOTE: By default the serial timeout is disabled as it causes lost characters
> - * over the serial ports. This means that the UART clocks will stay on until
> - * disabled via sysfs. This also causes that any deeper omap sleep states are
> - * blocked.
> + * NOTE: By default the serial auto_suspend timeout is disabled as it causes
> + * lost characters over the serial ports. This means that the UART clocks will
> + * stay on until power/autosuspend_delay is set for the uart from sysfs.
> + * This also causes that any deeper omap sleep states are blocked.
> */
> -#define DEFAULT_TIMEOUT 0
> +#define DEFAULT_AUTOSUSPEND_DELAY -1
>
> #define MAX_UART_HWMOD_NAME_LEN 16
>
> static u8 num_uarts;
>
> +#define DEFAULT_RXDMA_TIMEOUT 1 /* RX DMA polling rate (us) */
> +#define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */
> +
> +static struct omap_uart_port_info omap_serial_default_info[] = {
This could be __initdata
> + {
> + .dma_enabled = 0,
This field is a bool, use 'false' instead of 0.
> + .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
> + .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
> + .autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY,
> + },
> +};
> +
> static int uart_idle_hwmod(struct omap_device *od)
> {
> omap_hwmod_idle(od->hwmods[0]);
> @@ -298,6 +310,7 @@ core_initcall(omap_serial_early_init);
> /**
> * omap_serial_init_port() - initialize single serial port
> * @bdata: port specific board data pointer
> + * @info: platform specific data pointer
> *
> * This function initialies serial driver for given port only.
> * Platforms can call this function instead of omap_serial_init()
> @@ -306,7 +319,8 @@ core_initcall(omap_serial_early_init);
> * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
> * use only one of the two.
> */
> -void __init omap_serial_init_port(struct omap_board_data *bdata)
> +void __init omap_serial_init_port(struct omap_board_data *bdata,
> + struct omap_uart_port_info *info)
alignment. 2nd argument should align with 1st
> {
> struct omap_hwmod *oh;
> struct platform_device *pdev;
> @@ -325,6 +339,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
> if (!oh)
> return;
>
> + if (info == NULL)
if (!info)
there's another one of these elsewhere in the patch too.
[...]
Kevin
^ permalink raw reply
* [PATCH v6 14/16] OMAP2+: UART: Take console_lock in suspend path if not taken
From: Kevin Hilman @ 2011-10-11 19:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317380561-661-5-git-send-email-govindraj.raja@ti.com>
"Govindraj.R" <govindraj.raja@ti.com> writes:
> In suspend path the console_lock is taken by uart_port_suspend
> however when no_console_suspend is used console_lock is not taken.
>
> During system wide suspend omap_pwr_domain hooks cut all
> clocks that are left enabled. So its unsafe to proceed printing after
> clocks are cut by pwr_domain hooks.
As I've mentioned in previous reviews, when no_console_suspend is
enabled, the user has explicitly requested console output during
suspend. In order to support that, we should not be cutting clocks at
all in that mode.
One way to address this would be to just disable runtime PM in the
->prepare method of the driver if no_console_suspend is enabled.
> Also pm_runtime will be disabled after dpm_suspend devices happens.
Not sure why this is relevant.
> So buffer all prints in suspend path by taking console_lock and print
> them back safely after power domain hooks re-enable clocks back.
>
> Use CONFIG_SERIAL_OMAP_CONSOLE macro check to take console_lock since
> console ops are available only if omap console is defined.
> omap-serial can be built as module without console support.
Please revisit use of #ifdefs. (c.f. #ifdefs are ugly in
Documentation/SubmittingPatches)
Kevin
^ permalink raw reply
* [GIT PULL] DEBUG_LL platform updates for 3.2
From: Arnd Bergmann @ 2011-10-11 19:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111011184821.GA11839@mudshark.cambridge.arm.com>
On Tuesday 11 October 2011 19:48:21 Will Deacon wrote:
> On Tue, Oct 11, 2011 at 04:09:15PM +0100, Will Deacon wrote:
> > For the cpu-mapping, I depend on:
> >
> > ARM: 7011/1: Add ARM cpu topology definition
> > ARM: 7060/1: smp: populate logical CPU mapping during boot
> > ARM: 7061/1: gic: convert logical CPU numbers into physical numbers
> >
> > which I can only see in Russell's for-next branch.
> >
> > For the debug-ll stuff, I depend on:
> >
> > ARM: 7072/1: debug: use kconfig choice for selecting DEBUG_LL UART
> >
> > and conflict with:
> >
> > ARM: 7097/1: debug: Move DEBUG_ICEDCC into the DEBUG_LL choice
> > ARM: 7096/1: debug: Add UART1 config choices
> > ARM: 7116/1: debug: provide dummy default option for DEBUG_LL UART choice
> > ARM: 7073/1: debug: augment DEBUG_LL Kconfig help to clarify behaviour
>
> I've stuck a debug-ll branch and a cpu-mapping branch here:
>
> git://github.com/wdeacon/linux-wd.git
Ok, thanks.
> (I finally gave up with my old broken git server!)
>
> These branches are based against -rc9 and I've cherry-picked the
> dependencies from Russell's for-next branch. I'm not sure that's good for
> anything, but it at least helps to show what's already in Russell's tree
> and what's currently outstanding.
I've stuck them into the arm-soc tree for now, so we get linux-next
coverage, but I won't send them to Linus this way because then we
would get the same commits twice in the history.
Russell, would be mind putting the 8 patches that Will listed above
into the devel-stable or some other non-rebasing branch so we can
rebase Will's patches on top of that?
Alternatively, if you prefer you could also throw them out of your
tree so I can send them to Linus, or you could pull the two patch
series from Will into your arm tree so I can drop them completely.
Arnnd
^ permalink raw reply
* [PATCH] arm/tegra: Harmony: Configure PMC for low-level interrupts
From: Olof Johansson @ 2011-10-11 19:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <74CDBE0F657A3D45AFBB94109FB122FF173BE19AC3@HQMAIL01.nvidia.com>
On Tue, Oct 11, 2011 at 10:03 AM, Stephen Warren <swarren@nvidia.com> wrote:
> Stephen Warren wrote at Wednesday, September 21, 2011 4:11 PM:
>> Without this, the PMC continually detects an interrupt when the PMU_IRQ
>> line is high, causing the tps6686x IRQ handler thread to hog an entire
>> CPU.
>>
>> This change was originally written by Wei Ni <wni@nvidia.com> for Seaboard
>> in the ChromeOS kernel.
>>
>> Long-term, this should probably be moved into some kind of PMU driver,
>> or perhaps integrated into the GPIO/IRQ/pinmux system?
>
> Olof, is this change OK for inclusion? Or, should we create some kind
> of PMU driver and interrupt controller to solve this?
I'm OK with it going in now as it is, but as we move to more things to
device-tree, having a common piece of code that does it based on
properties there would make sense. Today I think every single board
needs it.
I'll pick up the patch and push it out later today.
-Olof
^ permalink raw reply
* [PATCH v3 6/7] ARM: pxa: move gpio-pxa.h into include directory
From: Linus Walleij @ 2011-10-11 19:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318339051-19096-7-git-send-email-haojian.zhuang@marvell.com>
2011/10/11 Haojian Zhuang <haojian.zhuang@marvell.com>:
> Merge the gpio-pxa.h in arch-pxa and arch-mmp. Move the new gpio-pxa.h
> into include directory.
(...)
> ?arch/arm/plat-pxa/include/plat/gpio-pxa.h ?| ? 80 ---------------------------
> ?drivers/gpio/gpio-pxa.c ? ? ? ? ? ? ? ? ? ?| ? 42 ++++++++++++++-
> ?include/linux/gpio-pxa.h ? ? ? ? ? ? ? ? ? | ? 81 ++++++++++++++++++++++++++++
This seems like a fully valid merge of common pxa GPIO include
files. And I guess if both are not using plat-pxa it cannot reside
in <plat/gpio-pxa.h>?
Grant: shall this be <linux/gpio-pxa.h> or <linux/gpio/pxa.h> or so?
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v2 0/4] arm/tegra: Convert GPIO and pinmux to platform devs
From: Stephen Warren @ 2011-10-11 20:23 UTC (permalink / raw)
To: linux-arm-kernel
v2: Convert GPIO driver to ioremap its registers instead of using static
mappings. The pinmux driver doesn't do this yet, but will soon. However,
the pinmux register resources/DT-properties are set up correctly for when
the driver is converted. Also, add back initialization of
tegra_gpio_chip.of_node.
Stephen Warren (4):
arm/tegra: Prep boards for gpio/pinmux conversion to pdevs
arm/dt: Tegra: Add pinmux node to tegra20.dtsi
gpio/tegra: Convert to a platform device
arm/tegra: Convert pinmux driver to a platform device
.../devicetree/bindings/pinmux/pinmux_nvidia.txt | 5 +
arch/arm/boot/dts/tegra20.dtsi | 8 +
arch/arm/mach-tegra/board-harmony-pinmux.c | 8 +
arch/arm/mach-tegra/board-paz00-pinmux.c | 8 +
arch/arm/mach-tegra/board-seaboard-pinmux.c | 9 +-
arch/arm/mach-tegra/board-trimslice-pinmux.c | 7 +
arch/arm/mach-tegra/devices.c | 84 ++++++++++++
arch/arm/mach-tegra/devices.h | 2 +
arch/arm/mach-tegra/pinmux.c | 26 ++++
drivers/gpio/gpio-tegra.c | 142 +++++++++++++-------
10 files changed, 250 insertions(+), 49 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
^ permalink raw reply
* [PATCH v2 1/4] arm/tegra: Prep boards for gpio/pinmux conversion to pdevs
From: Stephen Warren @ 2011-10-11 20:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318364638-20191-1-git-send-email-swarren@nvidia.com>
The Tegra GPIO driver will be converted from static registration via
postcore_initcall() to be a platform device later in this patch series.
A new Tegra pinmux platform device will also be added.
Prepare for this by modifying all boards to register the appropriate
platform devices before-hand, so that when the drivers are converted,
those devices will be probed, and git bisectability will be maintained.
v2: Add resource definitions for GPIO and pinmux
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/mach-tegra/board-harmony-pinmux.c | 8 +++
arch/arm/mach-tegra/board-paz00-pinmux.c | 8 +++
arch/arm/mach-tegra/board-seaboard-pinmux.c | 9 ++-
arch/arm/mach-tegra/board-trimslice-pinmux.c | 7 ++
arch/arm/mach-tegra/devices.c | 84 ++++++++++++++++++++++++++
arch/arm/mach-tegra/devices.h | 2 +
6 files changed, 116 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
index 4d63e2e..e99b456 100644
--- a/arch/arm/mach-tegra/board-harmony-pinmux.c
+++ b/arch/arm/mach-tegra/board-harmony-pinmux.c
@@ -20,6 +20,7 @@
#include "gpio-names.h"
#include "board-harmony.h"
+#include "devices.h"
static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
@@ -140,6 +141,11 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD2_WP, .enable = true },
@@ -155,6 +161,8 @@ static struct tegra_gpio_table gpio_table[] = {
void harmony_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
index 2225769..fb20894 100644
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ b/arch/arm/mach-tegra/board-paz00-pinmux.c
@@ -20,6 +20,7 @@
#include "gpio-names.h"
#include "board-paz00.h"
+#include "devices.h"
static struct tegra_pingroup_config paz00_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
@@ -140,6 +141,11 @@ static struct tegra_pingroup_config paz00_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD1_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD1_WP, .enable = true },
@@ -152,6 +158,8 @@ static struct tegra_gpio_table gpio_table[] = {
void paz00_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
index 74f78b7..f092298 100644
--- a/arch/arm/mach-tegra/board-seaboard-pinmux.c
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -21,6 +21,7 @@
#include "gpio-names.h"
#include "board-seaboard.h"
+#include "devices.h"
#define DEFAULT_DRIVE(_name) \
{ \
@@ -157,8 +158,10 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
-
-
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
@@ -173,6 +176,8 @@ static struct tegra_gpio_table gpio_table[] = {
void __init seaboard_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
index bcb1916..4969dd2 100644
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -21,6 +21,7 @@
#include "gpio-names.h"
#include "board-trimslice.h"
+#include "devices.h"
static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
@@ -141,6 +142,11 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true }, /* mmc4 cd */
{ .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true }, /* mmc4 wp */
@@ -151,6 +157,7 @@ static struct tegra_gpio_table gpio_table[] = {
void __init trimslice_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
}
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 57e35d2..240d5dc 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -31,6 +31,90 @@
#include <mach/usb_phy.h>
#include "gpio-names.h"
+static struct resource gpio_resource[] = {
+ [0] = {
+ .start = TEGRA_GPIO_BASE,
+ .end = TEGRA_GPIO_BASE + TEGRA_GPIO_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_GPIO1,
+ .end = INT_GPIO1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = INT_GPIO2,
+ .end = INT_GPIO2,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = INT_GPIO3,
+ .end = INT_GPIO3,
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .start = INT_GPIO4,
+ .end = INT_GPIO4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .start = INT_GPIO5,
+ .end = INT_GPIO5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .start = INT_GPIO6,
+ .end = INT_GPIO6,
+ .flags = IORESOURCE_IRQ,
+ },
+ [7] = {
+ .start = INT_GPIO7,
+ .end = INT_GPIO7,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device tegra_gpio_device = {
+ .name = "tegra-gpio",
+ .id = -1,
+ .resource = gpio_resource,
+ .num_resources = ARRAY_SIZE(gpio_resource),
+};
+
+static struct resource pinmux_resource[] = {
+ [0] = {
+ /* Tri-state registers */
+ .start = TEGRA_APB_MISC_BASE + 0x14,
+ .end = TEGRA_APB_MISC_BASE + 0x20 + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* Mux registers */
+ .start = TEGRA_APB_MISC_BASE + 0x80,
+ .end = TEGRA_APB_MISC_BASE + 0x9c + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ /* Pull-up/down registers */
+ .start = TEGRA_APB_MISC_BASE + 0xa0,
+ .end = TEGRA_APB_MISC_BASE + 0xb0 + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ /* Pad control registers */
+ .start = TEGRA_APB_MISC_BASE + 0x868,
+ .end = TEGRA_APB_MISC_BASE + 0x90c + 3,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device tegra_pinmux_device = {
+ .name = "tegra-pinmux",
+ .id = -1,
+ .resource = pinmux_resource,
+ .num_resources = ARRAY_SIZE(pinmux_resource),
+};
+
static struct resource i2c_resource1[] = {
[0] = {
.start = INT_I2C,
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 4a7dc0a..873ecb2 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -21,6 +21,8 @@
#include <linux/platform_device.h>
+extern struct platform_device tegra_gpio_device;
+extern struct platform_device tegra_pinmux_device;
extern struct platform_device tegra_sdhci_device1;
extern struct platform_device tegra_sdhci_device2;
extern struct platform_device tegra_sdhci_device3;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 2/4] arm/dt: Tegra: Add pinmux node to tegra20.dtsi
From: Stephen Warren @ 2011-10-11 20:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318364638-20191-1-git-send-email-swarren@nvidia.com>
Add a pinmux node to tegra20.dtsi in order to instantiate the future
pinmux device.
v2: Specify reg property precisely; don't just point at the whole APB_MISC
register range.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
.../devicetree/bindings/pinmux/pinmux_nvidia.txt | 5 +++++
arch/arm/boot/dts/tegra20.dtsi | 8 ++++++++
2 files changed, 13 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
diff --git a/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
new file mode 100644
index 0000000..36f82db
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 pinmux controller
+
+Required properties:
+- compatible : "nvidia,tegra20-pinmux"
+
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 5727595..65d7e6a 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -77,6 +77,14 @@
gpio-controller;
};
+ pinmux: pinmux at 70000000 {
+ compatible = "nvidia,tegra20-pinmux";
+ reg = < 0x70000014 0x10 /* Tri-state registers */
+ 0x70000080 0x20 /* Mux registers */
+ 0x700000a0 0x14 /* Pull-up/down registers */
+ 0x70000868 0xa8 >; /* Pad control registers */
+ };
+
serial at 70006000 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006000 0x40>;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 3/4] gpio/tegra: Convert to a platform device
From: Stephen Warren @ 2011-10-11 20:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318364638-20191-1-git-send-email-swarren@nvidia.com>
v2: Retrieve IRQ and memory addresses from resources instead of hard-
coding them. Add back initialization of tegra_gpio_chip.of_node.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
drivers/gpio/gpio-tegra.c | 142 ++++++++++++++++++++++++++++++---------------
1 files changed, 95 insertions(+), 47 deletions(-)
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 6b65207..3c0461a 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -20,10 +20,11 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
#include <asm/mach/irq.h>
@@ -35,9 +36,7 @@
#define GPIO_PORT(x) (((x) >> 3) & 0x3)
#define GPIO_BIT(x) ((x) & 0x7)
-#define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \
- GPIO_BANK(x) * 0x80 + \
- GPIO_PORT(x) * 4)
+#define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
#define GPIO_CNF(x) (GPIO_REG(x) + 0x00)
#define GPIO_OE(x) (GPIO_REG(x) + 0x10)
@@ -76,16 +75,20 @@ struct tegra_gpio_bank {
};
-static struct tegra_gpio_bank tegra_gpio_banks[] = {
- {.bank = 0, .irq = INT_GPIO1},
- {.bank = 1, .irq = INT_GPIO2},
- {.bank = 2, .irq = INT_GPIO3},
- {.bank = 3, .irq = INT_GPIO4},
- {.bank = 4, .irq = INT_GPIO5},
- {.bank = 5, .irq = INT_GPIO6},
- {.bank = 6, .irq = INT_GPIO7},
+void __iomem *regs;
+static struct tegra_gpio_bank tegra_gpio_banks[7] = {
};
+static inline void tegra_gpio_writel(u32 val, u32 reg)
+{
+ __raw_writel(val, regs + reg);
+}
+
+static inline u32 tegra_gpio_readl(u32 reg)
+{
+ return __raw_readl(regs + reg);
+}
+
static int tegra_gpio_compose(int bank, int port, int bit)
{
return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
@@ -98,7 +101,7 @@ static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
val = 0x100 << GPIO_BIT(gpio);
if (value)
val |= 1 << GPIO_BIT(gpio);
- __raw_writel(val, reg);
+ tegra_gpio_writel(val, reg);
}
void tegra_gpio_enable(int gpio)
@@ -118,7 +121,7 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+ return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
}
static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -155,7 +158,7 @@ static void tegra_gpio_irq_ack(struct irq_data *d)
{
int gpio = d->irq - INT_GPIO_BASE;
- __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+ tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
}
static void tegra_gpio_irq_mask(struct irq_data *d)
@@ -208,10 +211,10 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
spin_lock_irqsave(&bank->lvl_lock[port], flags);
- val = __raw_readl(GPIO_INT_LVL(gpio));
+ val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
val |= lvl_type << GPIO_BIT(gpio);
- __raw_writel(val, GPIO_INT_LVL(gpio));
+ tegra_gpio_writel(val, GPIO_INT_LVL(gpio));
spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
@@ -237,12 +240,12 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
for (port = 0; port < 4; port++) {
int gpio = tegra_gpio_compose(bank->bank, port, 0);
- unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
- __raw_readl(GPIO_INT_ENB(gpio));
- u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+ unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
+ tegra_gpio_readl(GPIO_INT_ENB(gpio));
+ u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio));
for_each_set_bit(pin, &sta, 8) {
- __raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+ tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio));
/* if gpio is edge triggered, clear condition
* before executing the hander so that we don't
@@ -276,11 +279,11 @@ void tegra_gpio_resume(void)
for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
unsigned int gpio = (b<<5) | (p<<3);
- __raw_writel(bank->cnf[p], GPIO_CNF(gpio));
- __raw_writel(bank->out[p], GPIO_OUT(gpio));
- __raw_writel(bank->oe[p], GPIO_OE(gpio));
- __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
- __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+ tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio));
+ tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio));
+ tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio));
+ tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+ tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
}
}
@@ -299,11 +302,11 @@ void tegra_gpio_suspend(void)
for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
unsigned int gpio = (b<<5) | (p<<3);
- bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
- bank->out[p] = __raw_readl(GPIO_OUT(gpio));
- bank->oe[p] = __raw_readl(GPIO_OE(gpio));
- bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
- bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+ bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio));
+ bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio));
+ bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
+ bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
+ bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
}
}
local_irq_restore(flags);
@@ -333,28 +336,55 @@ static struct irq_chip tegra_gpio_irq_chip = {
*/
static struct lock_class_key gpio_lock_class;
-static int __init tegra_gpio_init(void)
+static int __init tegra_gpio_probe(struct platform_device *pdev)
{
+ struct resource *res;
struct tegra_gpio_bank *bank;
int gpio;
int i;
int j;
+ for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing IRQ resource\n");
+ return -ENODEV;
+ }
+
+ bank = &tegra_gpio_banks[i];
+ bank->bank = i;
+ bank->irq = res->start;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing MEM resource\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res),
+ dev_name(&pdev->dev))) {
+ dev_err(&pdev->dev, "Couldn't request MEM resource\n");
+ return -ENODEV;
+ }
+
+ regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!regs) {
+ dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+ return -ENODEV;
+ }
+
for (i = 0; i < 7; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
- __raw_writel(0x00, GPIO_INT_ENB(gpio));
+ tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
}
}
#ifdef CONFIG_OF_GPIO
- /*
- * This isn't ideal, but it gets things hooked up until this
- * driver is converted into a platform_device
- */
- tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
- "nvidia,tegra20-gpio");
-#endif /* CONFIG_OF_GPIO */
+ tegra_gpio_chip.of_node = pdev->dev.of_node;
+#endif
gpiochip_add(&tegra_gpio_chip);
@@ -384,6 +414,24 @@ static int __init tegra_gpio_init(void)
return 0;
}
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-gpio", },
+ { },
+};
+
+static struct platform_driver tegra_gpio_driver = {
+ .driver = {
+ .name = "tegra-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra_gpio_of_match,
+ },
+ .probe = tegra_gpio_probe,
+};
+
+static int __init tegra_gpio_init(void)
+{
+ return platform_driver_register(&tegra_gpio_driver);
+}
postcore_initcall(tegra_gpio_init);
void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
@@ -416,13 +464,13 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
seq_printf(s,
"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
i, j,
- __raw_readl(GPIO_CNF(gpio)),
- __raw_readl(GPIO_OE(gpio)),
- __raw_readl(GPIO_OUT(gpio)),
- __raw_readl(GPIO_IN(gpio)),
- __raw_readl(GPIO_INT_STA(gpio)),
- __raw_readl(GPIO_INT_ENB(gpio)),
- __raw_readl(GPIO_INT_LVL(gpio)));
+ tegra_gpio_readl(GPIO_CNF(gpio)),
+ tegra_gpio_readl(GPIO_OE(gpio)),
+ tegra_gpio_readl(GPIO_OUT(gpio)),
+ tegra_gpio_readl(GPIO_IN(gpio)),
+ tegra_gpio_readl(GPIO_INT_STA(gpio)),
+ tegra_gpio_readl(GPIO_INT_ENB(gpio)),
+ tegra_gpio_readl(GPIO_INT_LVL(gpio)));
}
}
return 0;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 4/4] arm/tegra: Convert pinmux driver to a platform device
From: Stephen Warren @ 2011-10-11 20:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318364638-20191-1-git-send-email-swarren@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/mach-tegra/pinmux.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
index f80d507..46b9d87 100644
--- a/arch/arm/mach-tegra/pinmux.c
+++ b/arch/arm/mach-tegra/pinmux.c
@@ -20,6 +20,7 @@
#include <linux/errno.h>
#include <linux/spinlock.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include <mach/iomap.h>
#include <mach/pinmux.h>
@@ -665,6 +666,31 @@ void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *co
}
}
+static int __init tegra_pinmux_probe(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct of_device_id tegra_pinmux_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-pinmux", },
+ { },
+};
+
+static struct platform_driver tegra_pinmux_driver = {
+ .driver = {
+ .name = "tegra-pinmux",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra_pinmux_of_match,
+ },
+ .probe = tegra_pinmux_probe,
+};
+
+static int __init tegra_pinmux_init(void)
+{
+ return platform_driver_register(&tegra_pinmux_driver);
+}
+postcore_initcall(tegra_pinmux_init);
+
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/7] ARM: Add __arm_ioremap_exec for mapping external memory as MT_MEMORY
From: Andres Salomon @ 2011-10-11 20:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111007194543.18205.36115.stgit@kaulin.local>
On Fri, 07 Oct 2011 12:45:43 -0700
Tony Lindgren <tony@atomide.com> wrote:
> This allows mapping external memory such as SRAM for use.
>
> This is needed for some small chunks of code, such as reprogramming
> SDRAM memory source clocks that can't be executed in SDRAM. Other
> use cases include some PM related code.
Acked-by: Andres Salomon <dilinger@queued.net>
Looks good to me, thanks for doing this. I only have one very minor
quibble below, which could be addressed in a later patch..
>
> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> arch/arm/include/asm/io.h | 1 +
> arch/arm/mm/ioremap.c | 21 +++++++++++++++++++++
> 2 files changed, 22 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
> index d66605d..4ff152e 100644
> --- a/arch/arm/include/asm/io.h
> +++ b/arch/arm/include/asm/io.h
> @@ -80,6 +80,7 @@ extern void __iomem *__arm_ioremap_caller(unsigned
> long, size_t, unsigned int,
> extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long,
> size_t, unsigned int); extern void __iomem *__arm_ioremap(unsigned
> long, size_t, unsigned int); +extern void __iomem
> *__arm_ioremap_exec(unsigned long, size_t, int cached); extern void
> __iounmap(volatile void __iomem *addr);
> /*
> diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
> index ab50627..a2d94ac 100644
> --- a/arch/arm/mm/ioremap.c
> +++ b/arch/arm/mm/ioremap.c
> @@ -289,6 +289,27 @@ __arm_ioremap(unsigned long phys_addr, size_t
> size, unsigned int mtype) }
> EXPORT_SYMBOL(__arm_ioremap);
>
> +/*
> + * Remap an arbitrary physical address space into the kernel virtual
> + * address space as memory. Needed when the kernel wants to execute
> + * code in external memory. This is needed for reprogramming source
> + * clocks that would affect normal memory for example. Please see
> + * CONFIG_GENERIC_ALLOCATOR for allocating external memory.
> + */
> +void __iomem *
> +__arm_ioremap_exec(unsigned long phys_addr, size_t size, int cached)
I'd rather see this as 'bool cached', so it's clear we're talking
about a simple boolean (rather than bits).
> +{
> + unsigned int mtype;
> +
> + if (cached)
> + mtype = MT_MEMORY;
> + else
> + mtype = MT_MEMORY_NONCACHED;
> +
> + return __arm_ioremap_caller(phys_addr, size, mtype,
> + __builtin_return_address(0));
> +}
> +
> void __iounmap(volatile void __iomem *io_addr)
> {
> void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap"
> in the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH v3 6/7] ARM: pxa: move gpio-pxa.h into include directory
From: Arnd Bergmann @ 2011-10-11 20:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKnu2Mr3cWfo3SJYkBU2cXeKELhmVOv+Qes=SCWRBaSB-Sue3g@mail.gmail.com>
On Tuesday 11 October 2011 21:51:28 Linus Walleij wrote:
> 2011/10/11 Haojian Zhuang <haojian.zhuang@marvell.com>:
>
> > Merge the gpio-pxa.h in arch-pxa and arch-mmp. Move the new gpio-pxa.h
> > into include directory.
> (...)
> > arch/arm/plat-pxa/include/plat/gpio-pxa.h | 80 ---------------------------
> > drivers/gpio/gpio-pxa.c | 42 ++++++++++++++-
> > include/linux/gpio-pxa.h | 81 ++++++++++++++++++++++++++++
>
> This seems like a fully valid merge of common pxa GPIO include
> files. And I guess if both are not using plat-pxa it cannot reside
> in <plat/gpio-pxa.h>?
>
> Grant: shall this be <linux/gpio-pxa.h> or <linux/gpio/pxa.h> or so?
Hmm, more fundamentally, does this even need to be a header file?
Most of the header file looks like it should not be visible in the entire
kernel, so better move as much as possible into the gpio-pxa.c file.
I'm not sure how much remains in the end, but that should probably
determine the location (drivers/gpio/gpio-pxa.h, asm/gpio-pxa.h
or linux/gpio-pxa.h). In general, everything should be as local
as possible.
One more thing regarding the contents of the header:
> +/* GPIO Pin Level Registers */
> +#define PXA_GPLR(x) (*(volatile u32 *)(pxa_gpio_regs.gplr \
> + + PXA_BANK_OFF((x >> 5))))
> +/* GPIO Pin Direction Registers */
> +#define PXA_GPDR(x) (*(volatile u32 *)(pxa_gpio_regs.gpdr \
> + + PXA_BANK_OFF((x >> 5))))
When these get moved into the driver itself, it's probably a good
idea to turn these into proper accessors, something like
enum pxa_gpio_reg {
GPLR,
GPDR,
GPSR,
GPCR,
GRER,
GFER,
GEDR,
};
static void __iomem *pxa_gpio_reg_base;
static inline u32 pxa_gpio_read(unsigned int bank, enum pxa_gpio_reg reg)
{
unsigned offset = (bank < 3) ? bank << 2 : 0x100 + ((bank - 3) << 2);
return readl_relaxed(pxa_gpio_reg_base + offset + 12 * reg);
}
static inline void pxa_gpio_write(unsigned int bank, unsigned int reg, u32 val)
{
unsigned offset = (bank < 3) ? bank << 2 : 0x100 + ((bank - 3) << 2);
return writel_relaxed(val, pxa_gpio_reg_base + offset + 12 * reg);
}
That should let you get rid of most of the macros and the incorrect
'volatile' access.
Arnd
^ permalink raw reply
* [RFC PATCH v3] drivercore: Add driver probe deferral mechanism
From: Andrew Morton @ 2011-10-11 20:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110922184614.25419.84606.stgit@ponder>
On Thu, 22 Sep 2011 12:51:23 -0600
Grant Likely <grant.likely@secretlab.ca> wrote:
> Allow drivers to report at probe time that they cannot get all the resources
> required by the device, and should be retried at a later time.
>
> This should completely solve the problem of getting devices
> initialized in the right order. Right now this is mostly handled by
> mucking about with initcall ordering which is a complete hack, and
> doesn't even remotely handle the case where device drivers are in
> modules. This approach completely sidesteps the issues by allowing
> driver registration to occur in any order, and any driver can request
> to be retried after a few more other drivers get probed.
What happens is there is a circular dependency, or if a driver's
preconditions are never met? AFAICT the code keeps running the probe
function for ever.
If so: bad. The kernel should detect such situations, should
exhaustively report them and if possible, fix them up and struggle
onwards.
>
> ...
>
> + * This bit is tricky. We want to process every device in the
> + * deferred list, but devices can be removed from the list at any
> + * time while inside this for-each loop. There are two things that
> + * need to be protected against:
> + * - if the device is removed from the deferred_probe_list, then we
> + * loose our place in the loop. Since any device can be removed
s/loose/lose/
> + * asynchronously, list_for_each_entry_safe() wouldn't make things
> + * much better. Simplest solution is to restart walking the list
> + * whenever the current device gets removed. Not the most efficient,
> + * but is simple to implement and easy to audit for correctness.
> + * - if the device is unregistered, and freed, then there is a risk
> + * of a null pointer dereference. This code uses get/put_device()
> + * to ensure the device cannot disappear from under our feet.
> + */
>
> ...
>
> + /* Drop the mutex while probing each device; the probe path
> + * may manipulate the deferred list */
Please don't invent new coding styles. Like this:
/*
* Drop the mutex while probing each device; the probe path
* may manipulate the deferred list
*/
(entire patch)
>
> ...
>
^ permalink raw reply
* [PATCH v6 11/16] OMAP2+: UART: Move errata handling from serial.c to omap-serial
From: Kevin Hilman @ 2011-10-11 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317380561-661-2-git-send-email-govindraj.raja@ti.com>
"Govindraj.R" <govindraj.raja@ti.com> writes:
> Move the errata handling mechanism from serial.c to omap-serial file
> and utilise the same func in driver file.
>
> Errata i202, i291 are moved to be handled with omap-serial
> Moving the errata macro from serial.c file to driver header file
> as from on errata will be handled in driver file itself.
>
> Corrected errata id from chapter reference 2.15 to errata id i291.
>
> Acked-by: Alan Cox <alan@linux.intel.com>
> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
The errata handling for i291 is moved from device code to driver code
but it's functionality is also changed (but not described.)
In the current mainline code, The workaround for i291 is done whenever
UART clocks are about to be cut. When the clocks are (re)enabled, the
device is put back into no-idle.
This patch puts the device into force-idle just before the idle/suspend
transistion, but never puts it back into no-idle. So after the first
idle/suspend transition, the IP remains in force-idle forever. I don't
think that's what we want.
Kevin
^ permalink raw reply
* [PATCH v6 15/16] OMAP2+: UART: Enable back uart clocks with runtime API for early console
From: Kevin Hilman @ 2011-10-11 21:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317380561-661-6-git-send-email-govindraj.raja@ti.com>
"Govindraj.R" <govindraj.raja@ti.com> writes:
> For the early console probing we had avoided hwmod reset and idling
> and uart was idled using hwmod API and enabled back using omap_device API
> after omap_device registration.
>
> Now since we are using runtime API's to enable back uart, move hwmod
> idling and use runtime API to enable back UART.
>
> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
Now that the driver is using runtime PM. Why do we still need
HWMOD_INIT_NO_IDLE and HWMOD_INIT_NO_RESET?
The comment in the code says:
/*
* During UART early init, device need to be probed
* to determine SoC specific init before omap_device
* is ready. Therefore, don't allow idle here
*/
This was true when using the 8250 driver because it was not using
runtime PM so could not know how to (re)enable the device.
However, since the driver is now runtime PM adapted, any device access
should be contained within a runtime PM get/put block, so there should
no longer be a reason not allow the IP blocks to be reset during boot.
Kevin
^ permalink raw reply
* [PATCH v2 3/4] gpio/tegra: Convert to a platform device
From: Olof Johansson @ 2011-10-11 21:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318364638-20191-4-git-send-email-swarren@nvidia.com>
Hi,
Some nits below. Overall looks good.
On Tue, Oct 11, 2011 at 02:23:57PM -0600, Stephen Warren wrote:
> @@ -76,16 +75,20 @@ struct tegra_gpio_bank {
> };
>
>
> -static struct tegra_gpio_bank tegra_gpio_banks[] = {
> - {.bank = 0, .irq = INT_GPIO1},
> - {.bank = 1, .irq = INT_GPIO2},
> - {.bank = 2, .irq = INT_GPIO3},
> - {.bank = 3, .irq = INT_GPIO4},
> - {.bank = 4, .irq = INT_GPIO5},
> - {.bank = 5, .irq = INT_GPIO6},
> - {.bank = 6, .irq = INT_GPIO7},
> +void __iomem *regs;
Should be static.
> +static struct tegra_gpio_bank tegra_gpio_banks[7] = {
> };
Can be on the same line as the rest, i.e. ... = { };
> +static inline void tegra_gpio_writel(u32 val, u32 reg)
> +{
> + __raw_writel(val, regs + reg);
> +}
> +
> +static inline u32 tegra_gpio_readl(u32 reg)
> +{
> + return __raw_readl(regs + reg);
> +}
> +
> static int tegra_gpio_compose(int bank, int port, int bit)
> {
> return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
[...]
> @@ -333,28 +336,55 @@ static struct irq_chip tegra_gpio_irq_chip = {
> */
> static struct lock_class_key gpio_lock_class;
>
> -static int __init tegra_gpio_init(void)
> +static int __init tegra_gpio_probe(struct platform_device *pdev)
> {
> + struct resource *res;
> struct tegra_gpio_bank *bank;
> int gpio;
> int i;
> int j;
>
> + for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
> + res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
> + if (!res) {
> + dev_err(&pdev->dev, "Missing IRQ resource\n");
> + return -ENODEV;
> + }
> +
> + bank = &tegra_gpio_banks[i];
> + bank->bank = i;
> + bank->irq = res->start;
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "Missing MEM resource\n");
> + return -ENODEV;
> + }
> +
> + if (!devm_request_mem_region(&pdev->dev, res->start,
> + resource_size(res),
> + dev_name(&pdev->dev))) {
> + dev_err(&pdev->dev, "Couldn't request MEM resource\n");
> + return -ENODEV;
> + }
> +
> + regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
> + if (!regs) {
> + dev_err(&pdev->dev, "Couldn't ioremap regs\n");
> + return -ENODEV;
Should you release the mem region requested above here?
-Olof
^ permalink raw reply
* [PATCH v2 3/4] gpio/tegra: Convert to a platform device
From: Olof Johansson @ 2011-10-11 21:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111011212915.GA706@quad.lixom.net>
On Tue, Oct 11, 2011 at 2:29 PM, Olof Johansson <olof@lixom.net> wrote:
>> @@ -333,28 +336,55 @@ static struct irq_chip tegra_gpio_irq_chip = {
>> ? */
>> ?static struct lock_class_key gpio_lock_class;
>>
>> -static int __init tegra_gpio_init(void)
>> +static int __init tegra_gpio_probe(struct platform_device *pdev)
>> ?{
>> + ? ? struct resource *res;
>> ? ? ? struct tegra_gpio_bank *bank;
>> ? ? ? int gpio;
>> ? ? ? int i;
>> ? ? ? int j;
>>
>> + ? ? for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
>> + ? ? ? ? ? ? res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
>> + ? ? ? ? ? ? if (!res) {
>> + ? ? ? ? ? ? ? ? ? ? dev_err(&pdev->dev, "Missing IRQ resource\n");
>> + ? ? ? ? ? ? ? ? ? ? return -ENODEV;
>> + ? ? ? ? ? ? }
>> +
>> + ? ? ? ? ? ? bank = &tegra_gpio_banks[i];
>> + ? ? ? ? ? ? bank->bank = i;
>> + ? ? ? ? ? ? bank->irq = res->start;
>> + ? ? }
>> +
>> + ? ? res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + ? ? if (!res) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "Missing MEM resource\n");
>> + ? ? ? ? ? ? return -ENODEV;
>> + ? ? }
>> +
>> + ? ? if (!devm_request_mem_region(&pdev->dev, res->start,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?resource_size(res),
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?dev_name(&pdev->dev))) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "Couldn't request MEM resource\n");
>> + ? ? ? ? ? ? return -ENODEV;
>> + ? ? }
>> +
>> + ? ? regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
>> + ? ? if (!regs) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "Couldn't ioremap regs\n");
>> + ? ? ? ? ? ? return -ENODEV;
>
> Should you release the mem region requested above here?
As discussed on irc, this is handled by the driver core in case of
failed probe, so nevermind.
-Olof
^ permalink raw reply
* [PATCH v4 1/4] arm/tegra: Prep boards for gpio/pinmux conversion to pdevs
From: Stephen Warren @ 2011-10-11 22:16 UTC (permalink / raw)
To: linux-arm-kernel
The Tegra GPIO driver will be converted from static registration via
postcore_initcall() to be a platform device later in this patch series.
A new Tegra pinmux platform device will also be added.
Prepare for this by modifying all boards to register the appropriate
platform devices before-hand, so that when the drivers are converted,
those devices will be probed, and git bisectability will be maintained.
v2: Add resource definitions for GPIO and pinmux
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/mach-tegra/board-harmony-pinmux.c | 8 +++
arch/arm/mach-tegra/board-paz00-pinmux.c | 8 +++
arch/arm/mach-tegra/board-seaboard-pinmux.c | 9 ++-
arch/arm/mach-tegra/board-trimslice-pinmux.c | 7 ++
arch/arm/mach-tegra/devices.c | 84 ++++++++++++++++++++++++++
arch/arm/mach-tegra/devices.h | 2 +
6 files changed, 116 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
index 4d63e2e..e99b456 100644
--- a/arch/arm/mach-tegra/board-harmony-pinmux.c
+++ b/arch/arm/mach-tegra/board-harmony-pinmux.c
@@ -20,6 +20,7 @@
#include "gpio-names.h"
#include "board-harmony.h"
+#include "devices.h"
static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
@@ -140,6 +141,11 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD2_WP, .enable = true },
@@ -155,6 +161,8 @@ static struct tegra_gpio_table gpio_table[] = {
void harmony_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
index 2225769..fb20894 100644
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ b/arch/arm/mach-tegra/board-paz00-pinmux.c
@@ -20,6 +20,7 @@
#include "gpio-names.h"
#include "board-paz00.h"
+#include "devices.h"
static struct tegra_pingroup_config paz00_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
@@ -140,6 +141,11 @@ static struct tegra_pingroup_config paz00_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD1_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD1_WP, .enable = true },
@@ -152,6 +158,8 @@ static struct tegra_gpio_table gpio_table[] = {
void paz00_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
index 74f78b7..f092298 100644
--- a/arch/arm/mach-tegra/board-seaboard-pinmux.c
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -21,6 +21,7 @@
#include "gpio-names.h"
#include "board-seaboard.h"
+#include "devices.h"
#define DEFAULT_DRIVE(_name) \
{ \
@@ -157,8 +158,10 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
-
-
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
@@ -173,6 +176,8 @@ static struct tegra_gpio_table gpio_table[] = {
void __init seaboard_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
index bcb1916..4969dd2 100644
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -21,6 +21,7 @@
#include "gpio-names.h"
#include "board-trimslice.h"
+#include "devices.h"
static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
@@ -141,6 +142,11 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true }, /* mmc4 cd */
{ .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true }, /* mmc4 wp */
@@ -151,6 +157,7 @@ static struct tegra_gpio_table gpio_table[] = {
void __init trimslice_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
}
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 57e35d2..240d5dc 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -31,6 +31,90 @@
#include <mach/usb_phy.h>
#include "gpio-names.h"
+static struct resource gpio_resource[] = {
+ [0] = {
+ .start = TEGRA_GPIO_BASE,
+ .end = TEGRA_GPIO_BASE + TEGRA_GPIO_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_GPIO1,
+ .end = INT_GPIO1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = INT_GPIO2,
+ .end = INT_GPIO2,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = INT_GPIO3,
+ .end = INT_GPIO3,
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .start = INT_GPIO4,
+ .end = INT_GPIO4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .start = INT_GPIO5,
+ .end = INT_GPIO5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .start = INT_GPIO6,
+ .end = INT_GPIO6,
+ .flags = IORESOURCE_IRQ,
+ },
+ [7] = {
+ .start = INT_GPIO7,
+ .end = INT_GPIO7,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device tegra_gpio_device = {
+ .name = "tegra-gpio",
+ .id = -1,
+ .resource = gpio_resource,
+ .num_resources = ARRAY_SIZE(gpio_resource),
+};
+
+static struct resource pinmux_resource[] = {
+ [0] = {
+ /* Tri-state registers */
+ .start = TEGRA_APB_MISC_BASE + 0x14,
+ .end = TEGRA_APB_MISC_BASE + 0x20 + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* Mux registers */
+ .start = TEGRA_APB_MISC_BASE + 0x80,
+ .end = TEGRA_APB_MISC_BASE + 0x9c + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ /* Pull-up/down registers */
+ .start = TEGRA_APB_MISC_BASE + 0xa0,
+ .end = TEGRA_APB_MISC_BASE + 0xb0 + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ /* Pad control registers */
+ .start = TEGRA_APB_MISC_BASE + 0x868,
+ .end = TEGRA_APB_MISC_BASE + 0x90c + 3,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device tegra_pinmux_device = {
+ .name = "tegra-pinmux",
+ .id = -1,
+ .resource = pinmux_resource,
+ .num_resources = ARRAY_SIZE(pinmux_resource),
+};
+
static struct resource i2c_resource1[] = {
[0] = {
.start = INT_I2C,
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 4a7dc0a..873ecb2 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -21,6 +21,8 @@
#include <linux/platform_device.h>
+extern struct platform_device tegra_gpio_device;
+extern struct platform_device tegra_pinmux_device;
extern struct platform_device tegra_sdhci_device1;
extern struct platform_device tegra_sdhci_device2;
extern struct platform_device tegra_sdhci_device3;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v4 2/4] arm/dt: Tegra: Add pinmux node to tegra20.dtsi
From: Stephen Warren @ 2011-10-11 22:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318371375-4083-1-git-send-email-swarren@nvidia.com>
Add a pinmux node to tegra20.dtsi in order to instantiate the future
pinmux device.
v2: Specify reg property precisely; don't just point at the whole APB_MISC
register range.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
.../devicetree/bindings/pinmux/pinmux_nvidia.txt | 5 +++++
arch/arm/boot/dts/tegra20.dtsi | 8 ++++++++
2 files changed, 13 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
diff --git a/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
new file mode 100644
index 0000000..36f82db
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 pinmux controller
+
+Required properties:
+- compatible : "nvidia,tegra20-pinmux"
+
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 5727595..65d7e6a 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -77,6 +77,14 @@
gpio-controller;
};
+ pinmux: pinmux at 70000000 {
+ compatible = "nvidia,tegra20-pinmux";
+ reg = < 0x70000014 0x10 /* Tri-state registers */
+ 0x70000080 0x20 /* Mux registers */
+ 0x700000a0 0x14 /* Pull-up/down registers */
+ 0x70000868 0xa8 >; /* Pad control registers */
+ };
+
serial at 70006000 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006000 0x40>;
--
1.7.0.4
^ permalink raw reply related
* [PATCH v4 3/4] gpio/tegra: Convert to a platform device
From: Stephen Warren @ 2011-10-11 22:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318371375-4083-1-git-send-email-swarren@nvidia.com>
v3: Make regs variable static. Remove empty init of tegra_gpio_banks.
v2: Retrieve IRQ and memory addresses from resources instead of hard-
coding them. Add back initialization of tegra_gpio_chip.of_node.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
gpio fixup
---
drivers/gpio/gpio-tegra.c | 143 ++++++++++++++++++++++++++++++---------------
1 files changed, 95 insertions(+), 48 deletions(-)
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 6b65207..4cb59ed 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -20,10 +20,11 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
#include <asm/mach/irq.h>
@@ -35,9 +36,7 @@
#define GPIO_PORT(x) (((x) >> 3) & 0x3)
#define GPIO_BIT(x) ((x) & 0x7)
-#define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \
- GPIO_BANK(x) * 0x80 + \
- GPIO_PORT(x) * 4)
+#define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
#define GPIO_CNF(x) (GPIO_REG(x) + 0x00)
#define GPIO_OE(x) (GPIO_REG(x) + 0x10)
@@ -76,15 +75,18 @@ struct tegra_gpio_bank {
};
-static struct tegra_gpio_bank tegra_gpio_banks[] = {
- {.bank = 0, .irq = INT_GPIO1},
- {.bank = 1, .irq = INT_GPIO2},
- {.bank = 2, .irq = INT_GPIO3},
- {.bank = 3, .irq = INT_GPIO4},
- {.bank = 4, .irq = INT_GPIO5},
- {.bank = 5, .irq = INT_GPIO6},
- {.bank = 6, .irq = INT_GPIO7},
-};
+static void __iomem *regs;
+static struct tegra_gpio_bank tegra_gpio_banks[7];
+
+static inline void tegra_gpio_writel(u32 val, u32 reg)
+{
+ __raw_writel(val, regs + reg);
+}
+
+static inline u32 tegra_gpio_readl(u32 reg)
+{
+ return __raw_readl(regs + reg);
+}
static int tegra_gpio_compose(int bank, int port, int bit)
{
@@ -98,7 +100,7 @@ static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
val = 0x100 << GPIO_BIT(gpio);
if (value)
val |= 1 << GPIO_BIT(gpio);
- __raw_writel(val, reg);
+ tegra_gpio_writel(val, reg);
}
void tegra_gpio_enable(int gpio)
@@ -118,7 +120,7 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+ return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
}
static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -155,7 +157,7 @@ static void tegra_gpio_irq_ack(struct irq_data *d)
{
int gpio = d->irq - INT_GPIO_BASE;
- __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+ tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
}
static void tegra_gpio_irq_mask(struct irq_data *d)
@@ -208,10 +210,10 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
spin_lock_irqsave(&bank->lvl_lock[port], flags);
- val = __raw_readl(GPIO_INT_LVL(gpio));
+ val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
val |= lvl_type << GPIO_BIT(gpio);
- __raw_writel(val, GPIO_INT_LVL(gpio));
+ tegra_gpio_writel(val, GPIO_INT_LVL(gpio));
spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
@@ -237,12 +239,12 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
for (port = 0; port < 4; port++) {
int gpio = tegra_gpio_compose(bank->bank, port, 0);
- unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
- __raw_readl(GPIO_INT_ENB(gpio));
- u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+ unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
+ tegra_gpio_readl(GPIO_INT_ENB(gpio));
+ u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio));
for_each_set_bit(pin, &sta, 8) {
- __raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+ tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio));
/* if gpio is edge triggered, clear condition
* before executing the hander so that we don't
@@ -276,11 +278,11 @@ void tegra_gpio_resume(void)
for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
unsigned int gpio = (b<<5) | (p<<3);
- __raw_writel(bank->cnf[p], GPIO_CNF(gpio));
- __raw_writel(bank->out[p], GPIO_OUT(gpio));
- __raw_writel(bank->oe[p], GPIO_OE(gpio));
- __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
- __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+ tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio));
+ tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio));
+ tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio));
+ tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+ tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
}
}
@@ -299,11 +301,11 @@ void tegra_gpio_suspend(void)
for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
unsigned int gpio = (b<<5) | (p<<3);
- bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
- bank->out[p] = __raw_readl(GPIO_OUT(gpio));
- bank->oe[p] = __raw_readl(GPIO_OE(gpio));
- bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
- bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+ bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio));
+ bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio));
+ bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
+ bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
+ bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
}
}
local_irq_restore(flags);
@@ -333,28 +335,55 @@ static struct irq_chip tegra_gpio_irq_chip = {
*/
static struct lock_class_key gpio_lock_class;
-static int __init tegra_gpio_init(void)
+static int __init tegra_gpio_probe(struct platform_device *pdev)
{
+ struct resource *res;
struct tegra_gpio_bank *bank;
int gpio;
int i;
int j;
+ for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing IRQ resource\n");
+ return -ENODEV;
+ }
+
+ bank = &tegra_gpio_banks[i];
+ bank->bank = i;
+ bank->irq = res->start;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing MEM resource\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res),
+ dev_name(&pdev->dev))) {
+ dev_err(&pdev->dev, "Couldn't request MEM resource\n");
+ return -ENODEV;
+ }
+
+ regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!regs) {
+ dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+ return -ENODEV;
+ }
+
for (i = 0; i < 7; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
- __raw_writel(0x00, GPIO_INT_ENB(gpio));
+ tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
}
}
#ifdef CONFIG_OF_GPIO
- /*
- * This isn't ideal, but it gets things hooked up until this
- * driver is converted into a platform_device
- */
- tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
- "nvidia,tegra20-gpio");
-#endif /* CONFIG_OF_GPIO */
+ tegra_gpio_chip.of_node = pdev->dev.of_node;
+#endif
gpiochip_add(&tegra_gpio_chip);
@@ -384,6 +413,24 @@ static int __init tegra_gpio_init(void)
return 0;
}
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-gpio", },
+ { },
+};
+
+static struct platform_driver tegra_gpio_driver = {
+ .driver = {
+ .name = "tegra-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra_gpio_of_match,
+ },
+ .probe = tegra_gpio_probe,
+};
+
+static int __init tegra_gpio_init(void)
+{
+ return platform_driver_register(&tegra_gpio_driver);
+}
postcore_initcall(tegra_gpio_init);
void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
@@ -416,13 +463,13 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
seq_printf(s,
"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
i, j,
- __raw_readl(GPIO_CNF(gpio)),
- __raw_readl(GPIO_OE(gpio)),
- __raw_readl(GPIO_OUT(gpio)),
- __raw_readl(GPIO_IN(gpio)),
- __raw_readl(GPIO_INT_STA(gpio)),
- __raw_readl(GPIO_INT_ENB(gpio)),
- __raw_readl(GPIO_INT_LVL(gpio)));
+ tegra_gpio_readl(GPIO_CNF(gpio)),
+ tegra_gpio_readl(GPIO_OE(gpio)),
+ tegra_gpio_readl(GPIO_OUT(gpio)),
+ tegra_gpio_readl(GPIO_IN(gpio)),
+ tegra_gpio_readl(GPIO_INT_STA(gpio)),
+ tegra_gpio_readl(GPIO_INT_ENB(gpio)),
+ tegra_gpio_readl(GPIO_INT_LVL(gpio)));
}
}
return 0;
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox