Merge branch 'tegra/devel' into next/devel

This commit is contained in:
Arnd Bergmann 2011-10-20 18:15:30 +02:00
commit 1075329202
19 changed files with 535 additions and 160 deletions

View file

@ -0,0 +1,5 @@
NVIDIA Tegra 2 pinmux controller
Required properties:
- compatible : "nvidia,tegra20-pinmux"

View file

@ -0,0 +1,32 @@
/dts-v1/;
/memreserve/ 0x1c000000 0x04000000;
/include/ "tegra20.dtsi"
/ {
model = "NVIDIA Tegra2 Ventana evaluation board";
compatible = "nvidia,ventana", "nvidia,tegra20";
chosen {
bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init";
};
memory {
reg = < 0x00000000 0x40000000 >;
};
serial@70006300 {
clock-frequency = < 216000000 >;
};
sdhci@c8000400 {
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
power-gpios = <&gpio 155 0>; /* gpio PT3 */
};
sdhci@c8000600 {
power-gpios = <&gpio 70 0>; /* gpio PI6 */
support-8bit;
};
};

View file

@ -77,6 +77,14 @@
gpio-controller;
};
pinmux: pinmux@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@70006000 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006000 0x40>;

View file

@ -25,6 +25,7 @@ CONFIG_MACH_KAEN=y
CONFIG_MACH_PAZ00=y
CONFIG_MACH_TRIMSLICE=y
CONFIG_MACH_WARIO=y
CONFIG_MACH_VENTANA=y
CONFIG_TEGRA_DEBUG_UARTD=y
CONFIG_ARM_ERRATA_742230=y
CONFIG_NO_HZ=y
@ -38,7 +39,6 @@ CONFIG_HIGHMEM=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_VFP=y
CONFIG_PM=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@ -65,6 +65,7 @@ CONFIG_IPV6_TUNNEL=y
CONFIG_IPV6_MULTIPLE_TABLES=y
# CONFIG_WIRELESS is not set
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_MISC_DEVICES=y
CONFIG_AD525X_DPOT=y
@ -72,34 +73,61 @@ CONFIG_AD525X_DPOT_I2C=y
CONFIG_ICS932S401=y
CONFIG_APDS9802ALS=y
CONFIG_ISL29003=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_NET_ETHERNET=y
CONFIG_R8169=y
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set
CONFIG_USB_PEGASUS=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_SMSC75XX=y
CONFIG_USB_NET_SMSC95XX=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
# CONFIG_I2C_COMPAT is not set
# CONFIG_I2C_HELPER_AUTO is not set
CONFIG_I2C_TEGRA=y
CONFIG_SPI=y
CONFIG_SPI_TEGRA=y
CONFIG_SENSORS_LM90=y
CONFIG_MFD_TPS6586X=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_TPS6586X=y
# CONFIG_USB_SUPPORT is not set
CONFIG_SOUND=y
CONFIG_SND=y
# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_DRIVERS is not set
# CONFIG_SND_PCI is not set
# CONFIG_SND_ARM is not set
# CONFIG_SND_SPI is not set
# CONFIG_SND_USB is not set
CONFIG_SND_SOC=y
CONFIG_SND_SOC_TEGRA=y
CONFIG_SND_SOC_TEGRA_WM8903=y
CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_TEGRA=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_TEGRA=y
CONFIG_STAGING=y
# CONFIG_STAGING_EXCLUDE_BUILD is not set
CONFIG_IIO=y
CONFIG_SENSORS_ISL29018=y
CONFIG_SENSORS_AK8975=y
@ -123,18 +151,15 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_SLAB=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_SG=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_DEBUG_LL=y
CONFIG_EARLY_PRINTK=y
CONFIG_CRYPTO_ECB=y

View file

@ -69,6 +69,12 @@ config MACH_WARIO
help
Support for the Wario version of Seaboard
config MACH_VENTANA
bool "Ventana board"
select MACH_TEGRA_DT
help
Support for the nVidia Ventana development platform
choice
prompt "Low-level debug console UART"
default TEGRA_DEBUG_UART_NONE

View file

@ -31,6 +31,7 @@ obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o
obj-${CONFIG_MACH_TEGRA_DT} += board-dt.o
obj-${CONFIG_MACH_TEGRA_DT} += board-harmony-pinmux.o
obj-${CONFIG_MACH_TEGRA_DT} += board-seaboard-pinmux.o
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice.o
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice-pinmux.o

View file

@ -4,3 +4,4 @@ initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000
dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb

View file

@ -47,7 +47,7 @@
void harmony_pinmux_init(void);
void seaboard_pinmux_init(void);
void ventana_pinmux_init(void);
struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
@ -80,9 +80,19 @@ static struct of_device_id tegra_dt_gic_match[] __initdata = {
{}
};
static struct {
char *machine;
void (*init)(void);
} pinmux_configs[] = {
{ "nvidia,harmony", harmony_pinmux_init },
{ "nvidia,seaboard", seaboard_pinmux_init },
{ "nvidia,ventana", ventana_pinmux_init },
};
static void __init tegra_dt_init(void)
{
struct device_node *node;
int i;
node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
TEGRA_ARM_INT_DIST_BASE);
@ -91,10 +101,15 @@ static void __init tegra_dt_init(void)
tegra_clk_init_from_table(tegra_dt_clk_init_table);
if (of_machine_is_compatible("nvidia,harmony"))
harmony_pinmux_init();
else if (of_machine_is_compatible("nvidia,seaboard"))
seaboard_pinmux_init();
for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
if (of_machine_is_compatible(pinmux_configs[i].machine)) {
pinmux_configs[i].init();
break;
}
}
WARN(i == ARRAY_SIZE(pinmux_configs),
"Unknown platform! Pinmuxing not initialized\n");
/*
* Finished with the static registrations now; fill in the missing
@ -106,6 +121,7 @@ static void __init tegra_dt_init(void)
static const char * tegra_dt_board_compat[] = {
"nvidia,harmony",
"nvidia,seaboard",
"nvidia,ventana",
NULL
};

View file

@ -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));

View file

@ -18,10 +18,11 @@
#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"
@ -113,6 +114,16 @@ 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

@ -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 },
@ -149,6 +155,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));

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 NVIDIA Corporation
* Copyright (C) 2010,2011 NVIDIA Corporation
* Copyright (C) 2011 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
@ -21,6 +22,7 @@
#include "gpio-names.h"
#include "board-seaboard.h"
#include "devices.h"
#define DEFAULT_DRIVE(_name) \
{ \
@ -157,10 +159,33 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
{TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_DDC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_GMD, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_LSDA, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_PTA, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SLXK, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
};
static struct platform_device *pinmux_devices[] = {
&tegra_gpio_device,
&tegra_pinmux_device,
};
static struct tegra_gpio_table gpio_table[] = {
static struct tegra_gpio_table common_gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD2_WP, .enable = true },
{ .gpio = TEGRA_GPIO_SD2_POWER, .enable = true },
@ -169,12 +194,46 @@ static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_ISL29018_IRQ, .enable = true },
};
void __init seaboard_pinmux_init(void)
static void __init update_pinmux(struct tegra_pingroup_config *newtbl, int size)
{
int i, j;
struct tegra_pingroup_config *new_pingroup, *base_pingroup;
/* Update base seaboard pinmux table with secondary board
* specific pinmux table table.
*/
for (i = 0; i < size; i++) {
new_pingroup = &newtbl[i];
for (j = 0; j < ARRAY_SIZE(seaboard_pinmux); j++) {
base_pingroup = &seaboard_pinmux[j];
if (new_pingroup->pingroup == base_pingroup->pingroup) {
*base_pingroup = *new_pingroup;
break;
}
}
}
}
void __init seaboard_common_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,
ARRAY_SIZE(seaboard_drive_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
tegra_gpio_config(common_gpio_table, ARRAY_SIZE(common_gpio_table));
}
void __init seaboard_pinmux_init(void)
{
seaboard_common_pinmux_init();
}
void __init ventana_pinmux_init(void)
{
update_pinmux(ventana_pinmux, ARRAY_SIZE(ventana_pinmux));
seaboard_common_pinmux_init();
}

View file

@ -22,6 +22,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},
@ -142,6 +143,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 */
@ -152,6 +158,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));
}

View file

@ -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,

View file

@ -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;

View file

@ -199,6 +199,7 @@ struct tegra_drive_pingroup_config {
struct tegra_drive_pingroup_desc {
const char *name;
s16 reg_bank;
s16 reg;
};
@ -207,6 +208,9 @@ struct tegra_pingroup_desc {
int funcs[4];
int func_safe;
int vddio;
s16 tri_bank; /* Register bank the tri_reg exists within */
s16 mux_bank; /* Register bank the mux_reg exists within */
s16 pupd_bank; /* Register bank the pupd_reg exists within */
s16 tri_reg; /* offset into the TRISTATE_REG_* register bank */
s16 mux_reg; /* offset into the PIN_MUX_CTL_* register bank */
s16 pupd_reg; /* offset into the PULL_UPDOWN_REG_* register bank */

View file

@ -31,10 +31,16 @@
#include <mach/pinmux.h>
#include <mach/suspend.h>
#define TRISTATE_REG_A 0x14
#define PIN_MUX_CTL_REG_A 0x80
#define PULLUPDOWN_REG_A 0xa0
#define PINGROUP_REG_A 0x868
#define DRIVE_PINGROUP(pg_name, r) \
[TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \
.name = #pg_name, \
.reg = r \
.reg_bank = 3, \
.reg = ((r) - PINGROUP_REG_A) \
}
const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
@ -90,11 +96,14 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
TEGRA_MUX_ ## f3, \
}, \
.func_safe = TEGRA_MUX_ ## f_safe, \
.tri_reg = tri_r, \
.tri_bank = 0, \
.tri_reg = ((tri_r) - TRISTATE_REG_A), \
.tri_bit = tri_b, \
.mux_reg = mux_r, \
.mux_bank = 1, \
.mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A), \
.mux_bit = mux_b, \
.pupd_reg = pupd_r, \
.pupd_bank = 2, \
.pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \
.pupd_bit = pupd_b, \
}
@ -217,62 +226,3 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
PINGROUP(XM2C, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xA8, 30),
PINGROUP(XM2D, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, -1, -1, -1, -1, 0xA8, 28),
};
#ifdef CONFIG_PM
#define TRISTATE_REG_A 0x14
#define TRISTATE_REG_NUM 4
#define PIN_MUX_CTL_REG_A 0x80
#define PIN_MUX_CTL_REG_NUM 8
#define PULLUPDOWN_REG_A 0xa0
#define PULLUPDOWN_REG_NUM 5
static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
PULLUPDOWN_REG_NUM +
ARRAY_SIZE(tegra_soc_drive_pingroups)];
static inline unsigned long pg_readl(unsigned long offset)
{
return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
}
static inline void pg_writel(unsigned long value, unsigned long offset)
{
writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
}
void tegra_pinmux_suspend(void)
{
unsigned int i;
u32 *ctx = pinmux_reg;
for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
*ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
*ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
for (i = 0; i < TRISTATE_REG_NUM; i++)
*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
*ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg);
}
void tegra_pinmux_resume(void)
{
unsigned int i;
u32 *ctx = pinmux_reg;
for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4);
for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4);
for (i = 0; i < TRISTATE_REG_NUM; i++)
pg_writel(*ctx++, TRISTATE_REG_A + i*4);
for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg);
}
#endif

View file

@ -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>
@ -169,15 +170,17 @@ static const char *pupd_name(unsigned long val)
}
}
static int nbanks;
static void __iomem **regs;
static inline unsigned long pg_readl(unsigned long offset)
static inline u32 pg_readl(u32 bank, u32 reg)
{
return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
return readl(regs[bank] + reg);
}
static inline void pg_writel(unsigned long value, unsigned long offset)
static inline void pg_writel(u32 val, u32 bank, u32 reg)
{
writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
writel(val, regs[bank] + reg);
}
static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
@ -217,10 +220,10 @@ static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(pingroups[pg].mux_reg);
reg = pg_readl(pingroups[pg].mux_bank, pingroups[pg].mux_reg);
reg &= ~(0x3 << pingroups[pg].mux_bit);
reg |= mux << pingroups[pg].mux_bit;
pg_writel(reg, pingroups[pg].mux_reg);
pg_writel(reg, pingroups[pg].mux_bank, pingroups[pg].mux_reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -241,11 +244,11 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(pingroups[pg].tri_reg);
reg = pg_readl(pingroups[pg].tri_bank, pingroups[pg].tri_reg);
reg &= ~(0x1 << pingroups[pg].tri_bit);
if (tristate)
reg |= 1 << pingroups[pg].tri_bit;
pg_writel(reg, pingroups[pg].tri_reg);
pg_writel(reg, pingroups[pg].tri_bank, pingroups[pg].tri_reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -272,10 +275,10 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(pingroups[pg].pupd_reg);
reg = pg_readl(pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
reg &= ~(0x3 << pingroups[pg].pupd_bit);
reg |= pupd << pingroups[pg].pupd_bit;
pg_writel(reg, pingroups[pg].pupd_reg);
pg_writel(reg, pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -362,12 +365,12 @@ static int tegra_drive_pinmux_set_hsm(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(drive_pingroups[pg].reg);
reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
if (hsm == TEGRA_HSM_ENABLE)
reg |= (1 << 2);
else
reg &= ~(1 << 2);
pg_writel(reg, drive_pingroups[pg].reg);
pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -387,12 +390,12 @@ static int tegra_drive_pinmux_set_schmitt(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(drive_pingroups[pg].reg);
reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
if (schmitt == TEGRA_SCHMITT_ENABLE)
reg |= (1 << 3);
else
reg &= ~(1 << 3);
pg_writel(reg, drive_pingroups[pg].reg);
pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -412,10 +415,10 @@ static int tegra_drive_pinmux_set_drive(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(drive_pingroups[pg].reg);
reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x3 << 4);
reg |= drive << 4;
pg_writel(reg, drive_pingroups[pg].reg);
pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -435,10 +438,10 @@ static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(drive_pingroups[pg].reg);
reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x1f << 12);
reg |= pull_down << 12;
pg_writel(reg, drive_pingroups[pg].reg);
pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -458,10 +461,10 @@ static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(drive_pingroups[pg].reg);
reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x1f << 12);
reg |= pull_up << 12;
pg_writel(reg, drive_pingroups[pg].reg);
pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -481,10 +484,10 @@ static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(drive_pingroups[pg].reg);
reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x3 << 28);
reg |= slew_rising << 28;
pg_writel(reg, drive_pingroups[pg].reg);
pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -504,10 +507,10 @@ static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg,
spin_lock_irqsave(&mux_lock, flags);
reg = pg_readl(drive_pingroups[pg].reg);
reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
reg &= ~(0x3 << 30);
reg |= slew_falling << 30;
pg_writel(reg, drive_pingroups[pg].reg);
pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
spin_unlock_irqrestore(&mux_lock, flags);
@ -665,6 +668,99 @@ void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *co
}
}
static int __devinit tegra_pinmux_probe(struct platform_device *pdev)
{
struct resource *res;
int i;
int config_bad = 0;
for (i = 0; ; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
break;
}
nbanks = i;
for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
if (pingroups[i].tri_bank >= nbanks) {
dev_err(&pdev->dev, "pingroup %d: bad tri_bank\n", i);
config_bad = 1;
}
if (pingroups[i].mux_bank >= nbanks) {
dev_err(&pdev->dev, "pingroup %d: bad mux_bank\n", i);
config_bad = 1;
}
if (pingroups[i].pupd_bank >= nbanks) {
dev_err(&pdev->dev, "pingroup %d: bad pupd_bank\n", i);
config_bad = 1;
}
}
for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
if (drive_pingroups[i].reg_bank >= nbanks) {
dev_err(&pdev->dev,
"drive pingroup %d: bad reg_bank\n", i);
config_bad = 1;
}
}
if (config_bad)
return -ENODEV;
regs = devm_kzalloc(&pdev->dev, nbanks * sizeof(*regs), GFP_KERNEL);
if (!regs) {
dev_err(&pdev->dev, "Can't alloc regs pointer\n");
return -ENODEV;
}
for (i = 0; i < nbanks; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
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 %d\n", i);
return -ENODEV;
}
regs[i] = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!regs) {
dev_err(&pdev->dev, "Couldn't ioremap regs %d\n", i);
return -ENODEV;
}
}
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>
@ -684,6 +780,7 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
int len;
for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
unsigned long reg;
unsigned long tri;
unsigned long mux;
unsigned long pupd;
@ -696,8 +793,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
seq_printf(s, "TEGRA_MUX_NONE");
len = strlen("NONE");
} else {
mux = (pg_readl(pingroups[i].mux_reg) >>
pingroups[i].mux_bit) & 0x3;
reg = pg_readl(pingroups[i].mux_bank,
pingroups[i].mux_reg);
mux = (reg >> pingroups[i].mux_bit) & 0x3;
if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
len = 5;
@ -713,8 +811,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
seq_printf(s, "TEGRA_PUPD_NORMAL");
len = strlen("NORMAL");
} else {
pupd = (pg_readl(pingroups[i].pupd_reg) >>
pingroups[i].pupd_bit) & 0x3;
reg = pg_readl(pingroups[i].pupd_bank,
pingroups[i].pupd_reg);
pupd = (reg >> pingroups[i].pupd_bit) & 0x3;
seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
len = strlen(pupd_name(pupd));
}
@ -723,8 +822,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
if (pingroups[i].tri_reg < 0) {
seq_printf(s, "TEGRA_TRI_NORMAL");
} else {
tri = (pg_readl(pingroups[i].tri_reg) >>
pingroups[i].tri_bit) & 0x1;
reg = pg_readl(pingroups[i].tri_bank,
pingroups[i].tri_reg);
tri = (reg >> pingroups[i].tri_bit) & 0x1;
seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
}
@ -759,7 +859,8 @@ static int dbg_drive_pinmux_show(struct seq_file *s, void *unused)
dbg_pad_field(s, 7 - len);
reg = pg_readl(drive_pingroups[i].reg);
reg = pg_readl(drive_pingroups[i].reg_bank,
drive_pingroups[i].reg);
if (HSM_EN(reg)) {
seq_printf(s, "TEGRA_HSM_ENABLE");
len = 16;

View file

@ -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>
@ -34,9 +35,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)
@ -75,15 +74,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)
{
@ -97,7 +99,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)
@ -117,7 +119,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)
@ -150,7 +152,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)
@ -203,10 +205,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);
@ -232,12 +234,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
@ -271,11 +273,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));
}
}
@ -294,11 +296,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);
@ -328,27 +330,54 @@ 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 __devinit tegra_gpio_probe(struct platform_device *pdev)
{
struct resource *res;
struct tegra_gpio_bank *bank;
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);
@ -375,6 +404,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)
@ -407,13 +454,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;