Discussion:
[PATCH v3] OpenRD: Enable SD/UART selection for serial port 1
(too old to reply)
Tanmay Upadhyay
2010-08-11 05:21:02 UTC
Permalink
This patch enables user to use serial port 1 of the OpenRD device for SDIO
or UART(RS232/RS485). The selection can be done through kernel parameter.

By default the port would be used for SDIO. To select RS232 or RS485 mode,
pass string "uart=232" or "uart=485" respectively in the kernel parameters.
"uart=485" is ignored on OpenRD-Base as it doesn't have RS485 port.

Signed-off-by: Tanmay Upadhyay <***@einfochips.com>
---
arch/arm/mach-kirkwood/openrd-setup.c | 101 ++++++++++++++++++++++++++++++++-
1 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index fd06be6..46378c0 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -19,6 +19,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/kirkwood.h>
+#include <mach/gpio.h>
#include <plat/mvsdio.h>
#include "common.h"
#include "mpp.h"
@@ -57,7 +58,15 @@ static struct mvsdio_platform_data openrd_mvsdio_data = {
};

static unsigned int openrd_mpp_config[] __initdata = {
+ MPP12_SD_CLK,
+ MPP13_SD_CMD,
+ MPP14_SD_D0,
+ MPP15_SD_D1,
+ MPP16_SD_D2,
+ MPP17_SD_D3,
+ MPP28_GPIO,
MPP29_GPIO,
+ MPP34_GPIO,
0
};

@@ -67,6 +76,75 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
},
};

+static int __initdata uart1;
+
+static int __init sd_uart_selection(char *str)
+{
+ uart1 = -EINVAL;
+
+ /* Default is SD. Change if required, for UART */
+ if (!str)
+ return 0;
+
+ if (!strncmp(str, "232", 3)) {
+ uart1 = 232;
+ } else if (!strncmp(str, "485", 3)) {
+ /* OpenRD-Base doesn't have RS485. Treat is as an
+ * unknown argument & just have default setting -
+ * which is SD */
+ if (machine_is_openrd_base()) {
+ uart1 = -ENODEV;
+ return 1;
+ }
+
+ uart1 = 485;
+ }
+ return 1;
+}
+/* Parse boot_command_line string uart=232/485 */
+__setup("uart=", sd_uart_selection);
+
+static int __init uart1_mpp_config(void)
+{
+ /* Configure MPP for UART1 */
+ unsigned int uart1_mpp_config[] = {
+ MPP13_UART1_TXD,
+ MPP14_UART1_RXD,
+ 0
+ };
+
+ kirkwood_mpp_conf(uart1_mpp_config);
+
+ if (gpio_request(34, "SD_UART1_SEL")) {
+ printk(KERN_ERR "GPIO request failed for SD/UART1 selection"
+ ", gpio: 34\n");
+ return -EIO;
+ }
+
+ if (gpio_request(28, "RS232_RS485_SEL")) {
+ printk(KERN_ERR "GPIO request failed for RS232/RS485 selection"
+ ", gpio# 28\n");
+ gpio_free(34);
+ return -EIO;
+ }
+
+ /* Select UART1
+ * Pin # 34: 0 => UART1, 1 => SD */
+ gpio_direction_output(34, 0);
+
+ /* Select RS232 OR RS485
+ * Pin # 28: 0 => RS232, 1 => RS485 */
+ if (uart1 == 232)
+ gpio_direction_output(28, 0);
+ else
+ gpio_direction_output(28, 1);
+
+ gpio_free(34);
+ gpio_free(28);
+
+ return 0;
+}
+
static void __init openrd_init(void)
{
/*
@@ -90,7 +168,6 @@ static void __init openrd_init(void)
kirkwood_ge01_init(&openrd_ge01_data);

kirkwood_sata_init(&openrd_sata_data);
- kirkwood_sdio_init(&openrd_mvsdio_data);

kirkwood_i2c_init();

@@ -99,6 +176,28 @@ static void __init openrd_init(void)
ARRAY_SIZE(i2c_board_info));
kirkwood_audio_init();
}
+
+ if (uart1 <= 0) {
+ if (uart1 < 0)
+ printk(KERN_ERR "Invalid kernel parameter to select "
+ "UART1. Defaulting to SD. ERROR CODE: %d\n",
+ uart1);
+
+ /* Select SD
+ * Pin # 34: 0 => UART1, 1 => SD */
+ if (gpio_request(34, "SD_UART1_SEL")) {
+ printk(KERN_ERR "GPIO request failed for SD/UART1 "
+ "selection, gpio: 34\n");
+ } else {
+
+ gpio_direction_output(34, 1);
+ gpio_free(34);
+ kirkwood_sdio_init(&openrd_mvsdio_data);
+ }
+ } else {
+ if (!uart1_mpp_config())
+ kirkwood_uart1_init();
+ }
}

static int __init openrd_pci_init(void)
--
1.6.6.1
Russell King - ARM Linux
2010-08-11 07:27:13 UTC
Permalink
Post by Tanmay Upadhyay
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index fd06be6..46378c0 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -19,6 +19,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/kirkwood.h>
+#include <mach/gpio.h>
linux/gpio.h
Wu DaoGuang
2011-06-15 00:46:04 UTC
Permalink
This patch has been modified for the second time .Reduced the size
of the file ok2440_defconfig and updated to the latest APIs.

The ok2440 development board is based on SAMSUNG's S3C2440
microprocessor,which is developed with ARM920T core.

Thanks to Vasily Khoruzhick <***@gmail.com> for detailed
proposal in this patch.

This patch is against v3.0-rc3.

Signed-off-by: Wu DaoGuang <***@gmail.com>
---
arch/arm/configs/ok2440_defconfig | 384 +++++++++++++++++++++++++++++
arch/arm/mach-s3c2440/Kconfig | 10 +
arch/arm/mach-s3c2440/Makefile | 1 +
arch/arm/mach-s3c2440/mach-ok2440.c | 457 +++++++++++++++++++++++++++++++++++
4 files changed, 852 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/configs/ok2440_defconfig
create mode 100644 arch/arm/mach-s3c2440/mach-ok2440.c

diff --git a/arch/arm/configs/ok2440_defconfig b/arch/arm/configs/ok2440_defconfig
new file mode 100644
index 0000000..45f2c86
--- /dev/null
+++ b/arch/arm/configs/ok2440_defconfig
@@ -0,0 +1,384 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_RELAY=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_ARCH_S3C2410=y
+CONFIG_S3C_ADC=y
+CONFIG_S3C24XX_PWM=y
+CONFIG_MACH_OK2440=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_KEXEC=y
+CONFIG_CPU_IDLE=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+CONFIG_PM=y
+CONFIG_APM_EMULATION=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=m
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_NET_PKTGEN=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_REG_DEBUG=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=y
+CONFIG_RFD_FTL=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+CONFIG_MTD_NAND_S3C2410=y
+CONFIG_MTD_NAND_PLATFORM=y
+CONFIG_MTD_LPDDR=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_SG=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+CONFIG_NET_ETHERNET=y
+CONFIG_DM9000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_ZD1211RW_DEBUG=y
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIO_RAW=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_LEGACY_PTY_COUNT=128
+CONFIG_IPMI_HANDLER=m
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_S3C2410=y
+CONFIG_I2C_SIMTEC=y
+CONFIG_SPI=y
+CONFIG_SPI_S3C24XX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_SENSORS_LM75=y
+CONFIG_THERMAL=m
+CONFIG_WATCHDOG=y
+CONFIG_S3C2410_WATCHDOG=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_S3C2410=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_DISPLAY_SUPPORT=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_MINI_4x6=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_S3C24XX_SOC=y
+CONFIG_HIDRAW=y
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=m
+CONFIG_USB_WDM=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_S3C2410=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_MMC=y
+CONFIG_SDIO_UART=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SPI=y
+CONFIG_MMC_S3C=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_S3C24XX=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_DMADEVICES=y
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_INOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_DEBUG_USER=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=m
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index 50825a3..1214909 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -176,6 +176,16 @@ config MACH_AT2440EVB
help
Say Y here if you are using the AT2440EVB development board

+config MACH_OK2440
+ bool "OK2440 development board"
+ select CPU_S3C2440
+ select S3C2440_XTAL_12000000
+ select S3C_DEV_NAND
+ select S3C_DEV_USB_HOST
+ help
+ Say y here to select support for OK2440. Now it is widely used for
+ many students and Companies.
+
config MACH_MINI2440
bool "MINI2440 development board"
select CPU_S3C2440
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
index d5440fa..da4ad71 100644
--- a/arch/arm/mach-s3c2440/Makefile
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
+obj-$(CONFIG_MACH_OK2440) += mach-ok2440.o
obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
diff --git a/arch/arm/mach-s3c2440/mach-ok2440.c b/arch/arm/mach-s3c2440/mach-ok2440.c
new file mode 100644
index 0000000..43700e8
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-ok2440.c
@@ -0,0 +1,457 @@
+/* linux/arch/arm/mach-s3c2440/mach-ok2440.c
+ *
+ * Copyright (c) 2011 Feiling Embedded
+ * Base on mach-smdk2440.c by Ben Dooks <***@simtec.co.uk>
+ *
+ * Wu DaoGuang <***@gmail.com>
+ *
+ * Thanks to Dimity Andric and TomTom for the loan of an SMDK2440.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/dm9000.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/mmc/host.h>
+#include <linux/memblock.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
+
+#include <linux/leds.h>
+#include <linux/pwm.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/nand.h>
+#include <plat/iic.h>
+#include <plat/udc.h>
+#include <plat/mci.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/leds-gpio.h>
+#include <mach/regs-gpioj.h>
+#include <mach/regs-lcd.h>
+#include <mach/regs-mem.h>
+#include <mach/irqs.h>
+
+
+#include <mach/idle.h>
+#include <mach/fb.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <plat/gpio-cfg.h>
+#include <plat/usb-control.h>
+
+#include <plat/s3c2410.h>
+#include <plat/s3c244x.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+#include <plat/common-smdk.h>
+#include <sound/s3c24xx_uda134x.h>
+
+#define MACH_OK2440_DM9K_BASE (S3C2410_CS4 + 0x300)
+
+static struct map_desc ok2440_iodesc[] __initdata = {
+ /* ISA IO Space map (memory space selected by A24) */
+
+ {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD,
+ .pfn = __phys_to_pfn(S3C2410_CS2),
+ .length = 0x10000,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
+ .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+ .length = SZ_4M,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_BYTE,
+ .pfn = __phys_to_pfn(S3C2410_CS2),
+ .length = 0x10000,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
+ .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+ .length = SZ_4M,
+ .type = MT_DEVICE,
+ }
+};
+
+#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg ok2440_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ /* IR port */
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x43,
+ .ufcon = 0x51,
+ }
+};
+
+/* LCD driver info */
+
+static struct s3c2410fb_display ok2440_lcd_cfg __initdata = {
+
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+
+ .type = S3C2410_LCDCON1_TFT,
+
+ .width = 320,
+ .height = 240,
+
+ .pixclock = 270000, /* HCLK 60 MHz, divisor 10 */
+ .xres = 320,
+ .yres = 240,
+ .bpp = 16,
+ .left_margin = 8,
+ .right_margin = 5,
+ .hsync_len = 16,
+ .upper_margin = 8,
+ .lower_margin = 5,
+ .vsync_len = 2,
+};
+
+static struct s3c2410fb_mach_info ok2440_fb_info __initdata = {
+ .displays = &ok2440_lcd_cfg,
+ .num_displays = 1,
+ .default_display = 0,
+ .lpcsel = ((0xCE6) & ~7) | 1<<4,
+};
+
+/* Nand flash partitions on ok2440 */
+static struct mtd_partition ok2440_default_nand_part[] = {
+ [0] = {
+ .name = "u-boot",
+ .size = SZ_1M,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "App",
+ .size = SZ_2M,
+ .offset = MTDPART_OFS_APPEND,
+ },
+ [2] = {
+ .name = "Kernel",
+ .size = SZ_1M*4,
+ .offset = MTDPART_OFS_APPEND,
+ },
+ [3] = {
+ .name = "Ramdisk",
+ .size = SZ_16M,
+ .offset = MTDPART_OFS_APPEND,
+ },
+ [3] = {
+ .name = "Rootfs",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ },
+};
+static struct s3c2410_nand_set ok2440_nand_sets[] = {
+ [0] = {
+ .name = "nand",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(ok2440_default_nand_part),
+ .partitions = ok2440_default_nand_part,
+ .flash_bbt = 1, /* We use u-boot to creat a BBT*/
+ }
+};
+
+static struct s3c2410_platform_nand ok2440_nand_info __initdata = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(ok2440_nand_sets),
+ .sets = ok2440_nand_sets,
+ .ignore_unset_ecc = 1,
+};
+
+
+/* DM9000AEP 10/100 ethernet controller */
+static struct resource ok2440_dm9k_resource[] = {
+ [0] = {
+ .start = MACH_OK2440_DM9K_BASE,
+ .end = MACH_OK2440_DM9K_BASE + 3,
+ .flags = IORESOURCE_MEM
+ },
+ [1] = {
+ .start = MACH_OK2440_DM9K_BASE + 4,
+ .end = MACH_OK2440_DM9K_BASE + 7,
+ .flags = IORESOURCE_MEM
+ },
+ [2] = {
+ .start = IRQ_EINT7,
+ .end = IRQ_EINT7,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ }
+};
+/* The DM9000 has no eeprom ,and it's MAC address is set by
+ * the bootloader before starting the kernel.
+ */
+static struct dm9000_plat_data ok2440_dm9k_pdata = {
+ .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+};
+static struct platform_device ok2440_device_eth = {
+ .name = "dm9000",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ok2440_dm9k_resource),
+ .resource = ok2440_dm9k_resource,
+ .dev = {
+ .platform_data = &ok2440_dm9k_pdata,
+ },
+};
+
+/* LEDS sourport */
+static struct gpio_led ok2440_leds_desc[] = {
+ {
+ .name = "led0",
+ .default_trigger = "heartbeat",
+ .gpio = S3C2410_GPF(3),
+ },
+ {
+ .name = "led1",
+ .default_trigger = "nand-disk",
+ .gpio = S3C2410_GPF(4),
+ },
+ {
+ .name = "led2",
+ .default_trigger = "mmc",
+ .gpio = S3C2410_GPF(5),
+ },
+ {
+ .name = "led3",
+ .default_trigger = "network",
+ .gpio = S3C2410_GPF(6),
+ },
+};
+
+static struct gpio_led_platform_data ok2440_leds_pdata = {
+ .num_leds = ARRAY_SIZE(ok2440_leds_desc),
+ .leds = ok2440_leds_desc,
+};
+
+static struct platform_device ok2440_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &ok2440_leds_pdata,
+ },
+};
+/* GPIO KEYS */
+static struct gpio_keys_button ok2440_gpio_keys_table[] = {
+ {
+ .code = KEY_LEFT,
+ .gpio = S3C2410_GPF(0),
+ .active_low = 1,
+ .desc = "Left button",
+ },
+ {
+ .code = KEY_RIGHT,
+ .gpio = S3C2410_GPF(2),
+ .active_low = 1,
+ .desc = "Right button",
+ },
+ {
+ .code = KEY_UP,
+ .gpio = S3C2410_GPB(5),
+ .active_low = 1,
+ .desc = "Up button",
+ },
+ {
+ .code = KEY_DOWN,
+ .gpio = S3C2410_GPB(6),
+ .active_low = 1,
+ .desc = "Down button",
+ },
+ {
+ .code = KEY_ENTER,
+ .gpio = S3C2410_GPB(7),
+ .active_low = 1,
+ .desc = "Ok button",
+ },
+
+};
+static struct gpio_keys_platform_data ok2440_gpio_keys_pdata = {
+ .buttons = ok2440_gpio_keys_table,
+ .nbuttons = ARRAY_SIZE(ok2440_gpio_keys_table),
+};
+static struct platform_device ok2440_device_gpiokeys = {
+ .name = "gpio-keys",
+ .dev.platform_data = &ok2440_gpio_keys_pdata,
+};
+/* AUDIO */
+static struct s3c24xx_uda134x_platform_data ok2440_audio_pins = {
+ .l3_clk = S3C2410_GPB(4),
+ .l3_mode = S3C2410_GPB(2),
+ .l3_data = S3C2410_GPB(3),
+ .model = UDA134X_UDA1341
+};
+
+static struct platform_device ok2440_audio = {
+ .name = "s3c24xx_uda134x",
+ .id = 0,
+ .dev = {
+ .platform_data = &ok2440_audio_pins,
+ }
+};
+
+static struct platform_device uda1340_codec = {
+ .name = "uda134x-codec",
+ .id = -1,
+};
+
+/*
+ * I2C devices
+ */
+static struct at24_platform_data at24c08 = {
+ .byte_len = SZ_8K / 8,
+ .page_size = 16,
+};
+
+static struct i2c_board_info ok2440_i2c_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("24c08", 0x50),
+ .platform_data = &at24c08,
+ },
+};
+
+/* USB device UDC support */
+static struct s3c2410_udc_mach_info ok2440_udc_cfg __initdata = {
+ .pullup_pin = S3C2410_GPG(9),
+};
+
+/* USB */
+static struct s3c2410_hcd_info ok2440_usb_info __initdata = {
+ .port[0] = {
+ .flags = S3C_HCDFLG_USED,
+ },
+ .port[1] = {
+ .flags = 0,
+ },
+};
+
+/* MMC/SD */
+static struct s3c24xx_mci_pdata ok2440_mmc_cfg __initdata = {
+ .gpio_detect = S3C2410_GPG(10),
+ .gpio_wprotect = S3C2410_GPH(8),
+ .set_power = NULL,
+ .ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+
+struct syscore_ops s3c24xx_irq_syscore_ops = {
+ .suspend = s3c24xx_irq_suspend,
+ .resume = s3c24xx_irq_resume,
+};
+
+static struct platform_device *ok2440_devices[] __initdata = {
+ &s3c_device_ohci,
+ &s3c_device_lcd,
+ &s3c_device_wdt,
+ &s3c_device_i2c0,
+ &s3c_device_iis,
+ &s3c_device_sdi,
+ &s3c_device_nand,
+ &s3c_device_rtc,
+ &s3c_device_usbgadget,
+ &ok2440_device_gpiokeys,
+ &uda1340_codec,
+ &ok2440_device_eth,
+ &ok2440_audio,
+ &ok2440_leds,
+ &samsung_asoc_dma,
+
+};
+
+static void __init ok2440_map_io(void)
+{
+ s3c24xx_init_io(ok2440_iodesc, ARRAY_SIZE(ok2440_iodesc));
+ s3c24xx_init_clocks(12000000);
+ s3c24xx_init_uarts(ok2440_uartcfgs, ARRAY_SIZE(ok2440_uartcfgs));
+}
+
+static void __init ok2440_machine_init(void)
+{
+ /*configure the mmc protect to pull high . */
+ WARN_ON(gpio_request(S3C2410_GPG(8), "mmc pull up"));
+ gpio_direction_output(S3C2410_GPG(8), 1);
+ s3c24xx_fb_set_platdata(&ok2440_fb_info);
+ s3c_i2c0_set_platdata(NULL);
+
+ s3c_ohci_set_platdata(&ok2440_usb_info);
+
+ s3c_nand_set_platdata(&ok2440_nand_info);
+ s3c24xx_udc_set_platdata(&ok2440_udc_cfg);
+ s3c24xx_mci_set_platdata(&ok2440_mmc_cfg);
+ i2c_register_board_info(0, ok2440_i2c_devs,
+ ARRAY_SIZE(ok2440_i2c_devs));
+
+ platform_add_devices(ok2440_devices, ARRAY_SIZE(ok2440_devices));
+ s3c_pm_init();
+}
+
+MACHINE_START(S3C2440, "OK2440 development board.")
+ /* Maintainer: Wu DaoGuang <***@gmail.com> */
+ .boot_params = S3C2410_SDRAM_PA + 0x100,
+
+ .init_irq = s3c24xx_init_irq,
+ .map_io = ok2440_map_io,
+ .init_machine = ok2440_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
--
1.7.1
Tanmay Upadhyay
2011-06-22 05:55:37 UTC
Permalink
Tested UART console, Ethernet & I2C interfaces

v2 - move definitions from mfp-gplugd.h to mfp-pxa168.h

Signed-off-by: Tanmay Upadhyay <***@einfochips.com>
---
arch/arm/mach-mmp/Kconfig | 7 +
arch/arm/mach-mmp/Makefile | 1 +
arch/arm/mach-mmp/gplugd.c | 197 +++++++++++++++++++++++++++
arch/arm/mach-mmp/include/mach/mfp-pxa168.h | 37 +++++-
4 files changed, 237 insertions(+), 5 deletions(-)
create mode 100644 arch/arm/mach-mmp/gplugd.c

diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 67793a6..019d70a 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -77,6 +77,13 @@ config MACH_TETON_BGA
Say 'Y' here if you want to support the Marvell PXA168-based
Teton BGA Development Board.

+config MACH_SHEEVAD
+ bool "Marvell's PXA168 gplugD Board"
+ select CPU_PXA168
+ help
+ Say 'Y' here if you want to support the Marvell PXA168-based
+ GuruPlug Display(gplugD) Development Board
+
endmenu

config CPU_PXA168
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 5c68382..b0ac942 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_MACH_BROWNSTONE) += brownstone.o
obj-$(CONFIG_MACH_FLINT) += flint.o
obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
obj-$(CONFIG_MACH_TETON_BGA) += teton_bga.o
+obj-$(CONFIG_MACH_SHEEVAD) += gplugd.o
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
new file mode 100644
index 0000000..7fe2d12
--- /dev/null
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -0,0 +1,197 @@
+/*
+ * linux/arch/arm/mach-mmp/gplugd.c
+ *
+ * Support for the Marvell PXA168-based gplugD Development Platform.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/gpio.h>
+#include <mach/pxa168.h>
+#include <mach/mfp-pxa168.h>
+
+#include "common.h"
+
+static unsigned long gplugd_pin_config[] __initdata = {
+ /* UART3 */
+ GPIO8_UART3_TXD,
+ GPIO9_UART3_RXD,
+ GPI1O_UART3_CTS,
+ GPI11_UART3_RTS,
+
+ /* USB OTG PEN */
+ GPIO18_GPIO,
+
+ /* MMC2 */
+ GPIO28_MMC2_CMD,
+ GPIO29_MMC2_CLK,
+ GPIO30_MMC2_DAT0,
+ GPIO31_MMC2_DAT1,
+ GPIO32_MMC2_DAT2,
+ GPIO33_MMC2_DAT3,
+
+ /* LCD & HDMI clock selection GPIO: 0: 74.176MHz, 1: 74.25 MHz */
+ GPIO35_GPIO,
+ GPIO36_GPIO, /* CEC Interrupt */
+
+ /* MMC1 */
+ GPIO43_MMC1_CLK,
+ GPIO49_MMC1_CMD,
+ GPIO41_MMC1_DAT0,
+ GPIO40_MMC1_DAT1,
+ GPIO52_MMC1_DAT2,
+ GPIO51_MMC1_DAT3,
+ GPIO53_MMC1_CD,
+
+ /* LCD */
+ GPIO56_LCD_FCLK_RD,
+ GPIO57_LCD_LCLK_A0,
+ GPIO58_LCD_PCLK_WR,
+ GPIO59_LCD_DENA_BIAS,
+ GPIO60_LCD_DD0,
+ GPIO61_LCD_DD1,
+ GPIO62_LCD_DD2,
+ GPIO63_LCD_DD3,
+ GPIO64_LCD_DD4,
+ GPIO65_LCD_DD5,
+ GPIO66_LCD_DD6,
+ GPIO67_LCD_DD7,
+ GPIO68_LCD_DD8,
+ GPIO69_LCD_DD9,
+ GPIO70_LCD_DD10,
+ GPIO71_LCD_DD11,
+ GPIO72_LCD_DD12,
+ GPIO73_LCD_DD13,
+ GPIO74_LCD_DD14,
+ GPIO75_LCD_DD15,
+ GPIO76_LCD_DD16,
+ GPIO77_LCD_DD17,
+ GPIO78_LCD_DD18,
+ GPIO79_LCD_DD19,
+ GPIO80_LCD_DD20,
+ GPIO81_LCD_DD21,
+ GPIO82_LCD_DD22,
+ GPIO83_LCD_DD23,
+
+ /* GPIO */
+ GPIO84_GPIO,
+ GPIO85_GPIO,
+
+ /* Fast-Ethernet*/
+ GPIO86_TX_CLK,
+ GPIO87_TX_EN,
+ GPIO88_TX_DQ3,
+ GPIO89_TX_DQ2,
+ GPIO90_TX_DQ1,
+ GPIO91_TX_DQ0,
+ GPIO92_MII_CRS,
+ GPIO93_MII_COL,
+ GPIO94_RX_CLK,
+ GPIO95_RX_ER,
+ GPIO96_RX_DQ3,
+ GPIO97_RX_DQ2,
+ GPIO98_RX_DQ1,
+ GPIO99_RX_DQ0,
+ GPIO100_MII_MDC,
+ GPIO101_MII_MDIO,
+ GPIO103_RX_DV,
+ GPIO104_GPIO, /* Reset PHY */
+
+ /* RTC interrupt */
+ GPIO102_GPIO,
+
+ /* I2C */
+ GPIO105_CI2C_SDA,
+ GPIO106_CI2C_SCL,
+
+ /* SPI NOR Flash no SSP2 */
+ GPIO107_SSP2_RXD,
+ GPIO108_SSP2_TXD,
+ GPIO110_GPIO, /* SPI_CSn */
+ GPIO111_SSP2_CLK,
+
+ /* Select JTAG */
+ GPIO109_GPIO,
+
+ /* I2S */
+ GPIO114_I2S_FRM,
+ GPIO115_I2S_BCLK,
+ GPIO116_I2S_TXD
+};
+
+static struct i2c_board_info gplugd_i2c_board_info[] = {
+ {
+ .type = "isl1208",
+ .addr = 0x6F,
+ }
+};
+
+/* Bring PHY out of reset by setting GPIO 104 */
+static int gplugd_eth_init(void)
+{
+ if (unlikely(gpio_request(104, "ETH_RESET_N"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 104 to bring Ethernet "
+ "PHY out of reset\n");
+ return -EIO;
+ }
+
+ gpio_direction_output(104, 1);
+ gpio_free(104);
+ return 0;
+}
+
+struct pxa168_eth_platform_data gplugd_eth_platform_data = {
+ .port_number = 0,
+ .phy_addr = 0,
+ .speed = 0, /* Autonagotiation */
+ .init = gplugd_eth_init,
+};
+
+static void __init select_disp_freq(void)
+{
+ /* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */
+ if (unlikely(gpio_request(35, "DISP_FREQ_SEL"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 35 to select display "
+ "frequency\n");
+ } else {
+ gpio_direction_output(35, 1);
+ gpio_free(104);
+ }
+
+ if (unlikely(gpio_request(85, "DISP_FREQ_SEL_2"))) {
+ printk(KERN_ERR "Can't get hold of GPIO 85 to select display "
+ "frequency\n");
+ } else {
+ gpio_direction_output(85, 0);
+ gpio_free(104);
+ }
+}
+
+static void __init gplugd_init(void)
+{
+ mfp_config(ARRAY_AND_SIZE(gplugd_pin_config));
+
+ select_disp_freq();
+
+ /* on-chip devices */
+ pxa168_add_uart(3);
+ pxa168_add_ssp(0);
+ pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
+
+ pxa168_add_eth(&gplugd_eth_platform_data);
+}
+
+MACHINE_START(SHEEVAD, "PXA168-based gplugD Development Platform")
+ .map_io = mmp_map_io,
+ .nr_irqs = IRQ_BOARD_START,
+ .init_irq = pxa168_init_irq,
+ .timer = &pxa168_timer,
+ .init_machine = gplugd_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index 8c78232..bb2a4e1 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -217,6 +217,10 @@
#define GPIO111_UART1_DSR MFP_CFG(GPIO111, AF2)
#define GPIO112_UART1_DTR MFP_CFG(GPIO111, AF1)
#define GPIO112_UART1_DCD MFP_CFG(GPIO112, AF2)
+#define GPIO8_UART3_TXD MFP_CFG(GPIO8, AF2)
+#define GPIO9_UART3_RXD MFP_CFG(GPIO9, AF2)
+#define GPI1O_UART3_CTS MFP_CFG(GPIO10, AF2)
+#define GPI11_UART3_RTS MFP_CFG(GPIO11, AF2)

/* MMC1 */
#define GPIO37_MMC1_DAT7 MFP_CFG(GPIO37, AF1)
@@ -232,6 +236,22 @@
#define GPIO53_MMC1_CD MFP_CFG(GPIO53, AF1)
#define GPIO46_MMC1_WP MFP_CFG(GPIO46, AF1)

+/* MMC2 */
+#define GPIO28_MMC2_CMD MFP_CFG_DRV(GPIO28, AF6, FAST)
+#define GPIO29_MMC2_CLK MFP_CFG_DRV(GPIO29, AF6, FAST)
+#define GPIO30_MMC2_DAT0 MFP_CFG_DRV(GPIO30, AF6, FAST)
+#define GPIO31_MMC2_DAT1 MFP_CFG_DRV(GPIO31, AF6, FAST)
+#define GPIO32_MMC2_DAT2 MFP_CFG_DRV(GPIO32, AF6, FAST)
+#define GPIO33_MMC2_DAT3 MFP_CFG_DRV(GPIO33, AF6, FAST)
+
+/* MMC4 */
+#define GPIO125_MMC4_DAT3 MFP_CFG_DRV(GPIO125, AF7, FAST)
+#define GPIO126_MMC4_DAT2 MFP_CFG_DRV(GPIO126, AF7, FAST)
+#define GPIO127_MMC4_DAT1 MFP_CFG_DRV(GPIO127, AF7, FAST)
+#define GPIO0_2_MMC4_DAT0 MFP_CFG_DRV(GPIO0_2, AF7, FAST)
+#define GPIO1_2_MMC4_CMD MFP_CFG_DRV(GPIO1_2, AF7, FAST)
+#define GPIO2_2_MMC4_CLK MFP_CFG_DRV(GPIO2_2, AF7, FAST)
+
/* LCD */
#define GPIO84_LCD_CS MFP_CFG(GPIO84, AF1)
#define GPIO60_LCD_DD0 MFP_CFG(GPIO60, AF1)
@@ -269,11 +289,12 @@
#define GPIO106_CI2C_SCL MFP_CFG(GPIO106, AF1)

/* I2S */
-#define GPIO113_I2S_MCLK MFP_CFG(GPIO113,AF6)
-#define GPIO114_I2S_FRM MFP_CFG(GPIO114,AF1)
-#define GPIO115_I2S_BCLK MFP_CFG(GPIO115,AF1)
-#define GPIO116_I2S_RXD MFP_CFG(GPIO116,AF2)
-#define GPIO117_I2S_TXD MFP_CFG(GPIO117,AF2)
+#define GPIO113_I2S_MCLK MFP_CFG(GPIO113, AF6)
+#define GPIO114_I2S_FRM MFP_CFG(GPIO114, AF1)
+#define GPIO115_I2S_BCLK MFP_CFG(GPIO115, AF1)
+#define GPIO116_I2S_RXD MFP_CFG(GPIO116, AF2)
+#define GPIO117_I2S_TXD MFP_CFG(GPIO117, AF2)
+#define GPIO116_I2S_TXD MFP_CFG(GPIO116, AF1)

/* PWM */
#define GPIO96_PWM3_OUT MFP_CFG(GPIO96, AF1)
@@ -324,4 +345,10 @@
#define GPIO101_MII_MDIO MFP_CFG(GPIO101, AF5)
#define GPIO103_RX_DV MFP_CFG(GPIO103, AF5)

+/* SSP2 */
+#define GPIO107_SSP2_RXD MFP_CFG(GPIO107, AF4)
+#define GPIO108_SSP2_TXD MFP_CFG(GPIO108, AF4)
+#define GPIO111_SSP2_CLK MFP_CFG(GPIO111, AF4)
+#define GPIO112_SSP2_FRM MFP_CFG(GPIO112, AF4)
+
#endif /* __ASM_MACH_MFP_PXA168_H */
--
1.7.0.4
Vishwanath BS
2011-07-21 04:54:30 UTC
Permalink
From: Sripathy, Vishwanath <***@ti.com>

Add OMAP4460 OPP definitions for voltage and frequencies based on
OMAP4460 ES1.0 DM Operating Condition Addendum Version 0.1

The following exceptions are present:
* Smartreflex support is still on experimental mode: the gains and min
limits are currently pending characterization data. Currently OMAP4430 values
are used.
* Efuse offset for core OPP100-OV setting is not clear in documentation.
* IVA OPPs beyond OPP100 are disabled due to the delta between max OMAP4460
current requirements and Phoenix Max supply on VCORE2 in the default
configuration - boards which have supply which can support this should
explicitly call opp_enable and enable the same.
* MPU OPPs > OPPTURBO can easily be detected using a efuse burnt - currently
disabled pending clock changes to support DCC feature.

[***@ti.com: cleanups and updates from Datamanual]
Signed-off-by: Nishanth Menon <***@ti.com>
Signed-off-by: Vishwanath BS <***@ti.com>
---
Patch is generated against latest lo master.
Changes in V2: Updated the commit log as per Nishant's comments.
Patch has some checkpatch warnings related to line over 80 chars. They have
been retained to keep the readability of the code.

arch/arm/mach-omap2/control.h | 1 +
arch/arm/mach-omap2/omap_opp_data.h | 9 ++-
arch/arm/mach-omap2/opp4xxx_data.c | 96 ++++++++++++++++++++++---
arch/arm/mach-omap2/voltagedomains44xx_data.c | 14 +++-
4 files changed, 105 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index a016c8b..a41b9a7 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -195,6 +195,7 @@
#define OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO 0x249
#define OMAP44XX_CONTROL_FUSE_CORE_OPP50 0x254
#define OMAP44XX_CONTROL_FUSE_CORE_OPP100 0x257
+#define OMAP44XX_CONTROL_FUSE_CORE_OPP100OV 0x25A

/* AM35XX only CONTROL_GENERAL register offsets */
#define AM35XX_CONTROL_MSUSPENDMUX_6 (OMAP2_CONTROL_GENERAL + 0x0038)
diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h
index c784c12..18a750e 100644
--- a/arch/arm/mach-omap2/omap_opp_data.h
+++ b/arch/arm/mach-omap2/omap_opp_data.h
@@ -89,8 +89,11 @@ extern struct omap_volt_data omap34xx_vddcore_volt_data[];
extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
extern struct omap_volt_data omap36xx_vddcore_volt_data[];

-extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
+extern struct omap_volt_data omap443x_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap443x_vdd_iva_volt_data[];
+extern struct omap_volt_data omap443x_vdd_core_volt_data[];
+extern struct omap_volt_data omap446x_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap446x_vdd_iva_volt_data[];
+extern struct omap_volt_data omap446x_vdd_core_volt_data[];

#endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index 2293ba2..8c285e4 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -1,7 +1,7 @@
/*
* OMAP4 OPP table definitions.
*
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
* Nishanth Menon
* Kevin Hilman
* Thara Gopinath
@@ -36,7 +36,7 @@
#define OMAP4430_VDD_MPU_OPPTURBO_UV 1313000
#define OMAP4430_VDD_MPU_OPPNITRO_UV 1375000

-struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
+struct omap_volt_data omap443x_vdd_mpu_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
@@ -48,7 +48,7 @@ struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
#define OMAP4430_VDD_IVA_OPP100_UV 1188000
#define OMAP4430_VDD_IVA_OPPTURBO_UV 1300000

-struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
+struct omap_volt_data omap443x_vdd_iva_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
@@ -58,14 +58,14 @@ struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
#define OMAP4430_VDD_CORE_OPP50_UV 1025000
#define OMAP4430_VDD_CORE_OPP100_UV 1200000

-struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
+struct omap_volt_data omap443x_vdd_core_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(0, 0, 0, 0),
};


-static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
+static struct omap_opp_def __initdata omap443x_opp_def_list[] = {
/* MPU OPP1 - OPP50 */
OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV),
/* MPU OPP2 - OPP100 */
@@ -87,6 +87,82 @@ static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
/* TODO: add DSP, aess, fdif, gpu */
};

+#define OMAP4460_VDD_MPU_OPP50_UV 1025000
+#define OMAP4460_VDD_MPU_OPP100_UV 1200000
+#define OMAP4460_VDD_MPU_OPPTURBO_UV 1313000
+#define OMAP4460_VDD_MPU_OPPNITRO_UV 1375000
+
+struct omap_volt_data omap446x_vdd_mpu_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_IVA_OPP50_UV 1025000
+#define OMAP4460_VDD_IVA_OPP100_UV 1200000
+#define OMAP4460_VDD_IVA_OPPTURBO_UV 1313000
+#define OMAP4460_VDD_IVA_OPPNITRO_UV 1375000
+
+struct omap_volt_data omap446x_vdd_iva_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_CORE_OPP50_UV 1025000
+#define OMAP4460_VDD_CORE_OPP100_UV 1200000
+#define OMAP4460_VDD_CORE_OPP100_OV_UV 1250000
+
+struct omap_volt_data omap446x_vdd_core_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
+ /* MPU OPP1 - OPP50 */
+ OPP_INITIALIZER("mpu", true, 350000000, OMAP4460_VDD_MPU_OPP50_UV),
+ /* MPU OPP2 - OPP100 */
+ OPP_INITIALIZER("mpu", true, 700000000, OMAP4460_VDD_MPU_OPP100_UV),
+ /* MPU OPP3 - OPP-Turbo */
+ OPP_INITIALIZER("mpu", true, 920000000, OMAP4460_VDD_MPU_OPPTURBO_UV),
+ /*
+ * MPU OPP4 - OPP-Nitro + Disabled as the reference schematics
+ * recommends TPS623631 - confirm and enable the opp in board file
+ * XXX: May be we should enable these based on mpu capability and
+ * Exception board files disable it...
+ */
+ OPP_INITIALIZER("mpu", false, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
+ /* MPU OPP4 - OPP-Nitro SpeedBin */
+ OPP_INITIALIZER("mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
+ /* L3 OPP1 - OPP50 */
+ OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV),
+ /* L3 OPP2 - OPP100 */
+ OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV),
+ /* IVA OPP1 - OPP50 */
+ OPP_INITIALIZER("iva", true, 133000000, OMAP4460_VDD_IVA_OPP50_UV),
+ /* IVA OPP2 - OPP100 */
+ OPP_INITIALIZER("iva", true, 266100000, OMAP4460_VDD_IVA_OPP100_UV),
+ /*
+ * IVA OPP3 - OPP-Turbo + Disabled as the reference schematics
+ * recommends Phoenix VCORE2 which can supply only 600mA - so the ones
+ * above this OPP frequency, even though OMAP is capable, should be
+ * enabled by board file which is sure of the chip power capability
+ */
+ OPP_INITIALIZER("iva", false, 332000000, OMAP4460_VDD_IVA_OPPTURBO_UV),
+ /* IVA OPP4 - OPP-Nitro */
+ OPP_INITIALIZER("iva", false, 430000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
+ /* IVA OPP5 - OPP-Nitro SpeedBin*/
+ OPP_INITIALIZER("iva", false, 500000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
+
+ /* TODO: add DSP, aess, fdif, gpu */
+};
+
/**
* omap4_opp_init() - initialize omap4 opp table
*/
@@ -96,10 +172,12 @@ int __init omap4_opp_init(void)

if (!cpu_is_omap44xx())
return r;
-
- r = omap_init_opp_table(omap44xx_opp_def_list,
- ARRAY_SIZE(omap44xx_opp_def_list));
-
+ if (cpu_is_omap443x())
+ r = omap_init_opp_table(omap443x_opp_def_list,
+ ARRAY_SIZE(omap443x_opp_def_list));
+ else if (cpu_is_omap446x())
+ r = omap_init_opp_table(omap446x_opp_def_list,
+ ARRAY_SIZE(omap446x_opp_def_list));
return r;
}
device_initcall(omap4_opp_init);
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c
index cb64996..f516cfe 100644
--- a/arch/arm/mach-omap2/voltagedomains44xx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -91,9 +91,17 @@ static int __init omap44xx_voltage_early_init(void)
* XXX Will depend on the process, validation, and binning
* for the currently-running IC
*/
- omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data;
- omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data;
- omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data;
+ if (cpu_is_omap443x()) {
+ omap4_vdd_mpu_info.volt_data = omap443x_vdd_mpu_volt_data;
+ omap4_vdd_iva_info.volt_data = omap443x_vdd_iva_volt_data;
+ omap4_vdd_core_info.volt_data = omap443x_vdd_core_volt_data;
+ } else if (cpu_is_omap446x()) {
+ omap4_vdd_mpu_info.volt_data = omap446x_vdd_mpu_volt_data;
+ omap4_vdd_iva_info.volt_data = omap446x_vdd_iva_volt_data;
+ omap4_vdd_core_info.volt_data = omap446x_vdd_core_volt_data;
+ } else {
+ return -ENODATA;
+ }

return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
omap4_vdd_info,
--
1.7.0.4
Vishwanath Sripathy
2011-07-21 04:56:15 UTC
Permalink
My mailer seems to have goofed the from email-id. Pls ignore this email. I
have sent another patch correcting the same.

Vishwa
-----Original Message-----
Sent: Thursday, July 21, 2011 10:23 AM
Nishanth Menon
Subject: [PATCHV2] OMAP4: OPP: add OMAP4460 definitions
Add OMAP4460 OPP definitions for voltage and frequencies based on
OMAP4460 ES1.0 DM Operating Condition Addendum Version 0.1
* Smartreflex support is still on experimental mode: the gains and
min
limits are currently pending characterization data. Currently
OMAP4430 values
are used.
* Efuse offset for core OPP100-OV setting is not clear in
documentation.
* IVA OPPs beyond OPP100 are disabled due to the delta between max
OMAP4460
current requirements and Phoenix Max supply on VCORE2 in the
default
configuration - boards which have supply which can support this
should
explicitly call opp_enable and enable the same.
* MPU OPPs > OPPTURBO can easily be detected using a efuse burnt -
currently
disabled pending clock changes to support DCC feature.
---
Patch is generated against latest lo master.
Changes in V2: Updated the commit log as per Nishant's comments.
Patch has some checkpatch warnings related to line over 80 chars.
They have
been retained to keep the readability of the code.
arch/arm/mach-omap2/control.h | 1 +
arch/arm/mach-omap2/omap_opp_data.h | 9 ++-
arch/arm/mach-omap2/opp4xxx_data.c | 96
++++++++++++++++++++++---
arch/arm/mach-omap2/voltagedomains44xx_data.c | 14 +++-
4 files changed, 105 insertions(+), 15 deletions(-)
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-
omap2/control.h
index a016c8b..a41b9a7 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -195,6 +195,7 @@
#define OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO 0x249
#define OMAP44XX_CONTROL_FUSE_CORE_OPP50 0x254
#define OMAP44XX_CONTROL_FUSE_CORE_OPP100 0x257
+#define OMAP44XX_CONTROL_FUSE_CORE_OPP100OV 0x25A
/* AM35XX only CONTROL_GENERAL register offsets */
#define AM35XX_CONTROL_MSUSPENDMUX_6 (OMAP2_CONTROL_GENERAL +
0x0038)
diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-
omap2/omap_opp_data.h
index c784c12..18a750e 100644
--- a/arch/arm/mach-omap2/omap_opp_data.h
+++ b/arch/arm/mach-omap2/omap_opp_data.h
@@ -89,8 +89,11 @@ extern struct omap_volt_data
omap34xx_vddcore_volt_data[];
extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
extern struct omap_volt_data omap36xx_vddcore_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
+extern struct omap_volt_data omap443x_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap443x_vdd_iva_volt_data[];
+extern struct omap_volt_data omap443x_vdd_core_volt_data[];
+extern struct omap_volt_data omap446x_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap446x_vdd_iva_volt_data[];
+extern struct omap_volt_data omap446x_vdd_core_volt_data[];
#endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-
omap2/opp4xxx_data.c
index 2293ba2..8c285e4 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -1,7 +1,7 @@
/*
* OMAP4 OPP table definitions.
*
- * Copyright (C) 2010 Texas Instruments Incorporated -
http://www.ti.com/
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated -
http://www.ti.com/
* Nishanth Menon
* Kevin Hilman
* Thara Gopinath
@@ -36,7 +36,7 @@
#define OMAP4430_VDD_MPU_OPPTURBO_UV 1313000
#define OMAP4430_VDD_MPU_OPPNITRO_UV 1375000
-struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
+struct omap_volt_data omap443x_vdd_mpu_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV,
OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV,
OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV,
OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
@@ -48,7 +48,7 @@ struct omap_volt_data omap44xx_vdd_mpu_volt_data[]
= {
#define OMAP4430_VDD_IVA_OPP100_UV 1188000
#define OMAP4430_VDD_IVA_OPPTURBO_UV 1300000
-struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
+struct omap_volt_data omap443x_vdd_iva_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV,
OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV,
OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV,
OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
@@ -58,14 +58,14 @@ struct omap_volt_data
omap44xx_vdd_iva_volt_data[] = {
#define OMAP4430_VDD_CORE_OPP50_UV 1025000
#define OMAP4430_VDD_CORE_OPP100_UV 1200000
-struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
+struct omap_volt_data omap443x_vdd_core_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV,
OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV,
OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(0, 0, 0, 0),
};
-static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
+static struct omap_opp_def __initdata omap443x_opp_def_list[] = {
/* MPU OPP1 - OPP50 */
OPP_INITIALIZER("mpu", true, 300000000,
OMAP4430_VDD_MPU_OPP50_UV),
/* MPU OPP2 - OPP100 */
@@ -87,6 +87,82 @@ static struct omap_opp_def __initdata
omap44xx_opp_def_list[] = {
/* TODO: add DSP, aess, fdif, gpu */
};
+#define OMAP4460_VDD_MPU_OPP50_UV 1025000
+#define OMAP4460_VDD_MPU_OPP100_UV 1200000
+#define OMAP4460_VDD_MPU_OPPTURBO_UV 1313000
+#define OMAP4460_VDD_MPU_OPPNITRO_UV 1375000
+
+struct omap_volt_data omap446x_vdd_mpu_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV,
OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV,
OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV,
OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV,
OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_IVA_OPP50_UV 1025000
+#define OMAP4460_VDD_IVA_OPP100_UV 1200000
+#define OMAP4460_VDD_IVA_OPPTURBO_UV 1313000
+#define OMAP4460_VDD_IVA_OPPNITRO_UV 1375000
+
+struct omap_volt_data omap446x_vdd_iva_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV,
OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV,
OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV,
OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV,
OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_CORE_OPP50_UV 1025000
+#define OMAP4460_VDD_CORE_OPP100_UV 1200000
+#define OMAP4460_VDD_CORE_OPP100_OV_UV 1250000
+
+struct omap_volt_data omap446x_vdd_core_volt_data[] = {
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP50_UV,
OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV,
OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV,
OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16),
+ VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
+ /* MPU OPP1 - OPP50 */
+ OPP_INITIALIZER("mpu", true, 350000000,
OMAP4460_VDD_MPU_OPP50_UV),
+ /* MPU OPP2 - OPP100 */
+ OPP_INITIALIZER("mpu", true, 700000000,
OMAP4460_VDD_MPU_OPP100_UV),
+ /* MPU OPP3 - OPP-Turbo */
+ OPP_INITIALIZER("mpu", true, 920000000,
OMAP4460_VDD_MPU_OPPTURBO_UV),
+ /*
+ * MPU OPP4 - OPP-Nitro + Disabled as the reference schematics
+ * recommends TPS623631 - confirm and enable the opp in board
file
+ * XXX: May be we should enable these based on mpu capability
and
+ * Exception board files disable it...
+ */
+ OPP_INITIALIZER("mpu", false, 1200000000,
OMAP4460_VDD_MPU_OPPNITRO_UV),
+ /* MPU OPP4 - OPP-Nitro SpeedBin */
+ OPP_INITIALIZER("mpu", false, 1500000000,
OMAP4460_VDD_MPU_OPPNITRO_UV),
+ /* L3 OPP1 - OPP50 */
+ OPP_INITIALIZER("l3_main_1", true, 100000000,
OMAP4460_VDD_CORE_OPP50_UV),
+ /* L3 OPP2 - OPP100 */
+ OPP_INITIALIZER("l3_main_1", true, 200000000,
OMAP4460_VDD_CORE_OPP100_UV),
+ /* IVA OPP1 - OPP50 */
+ OPP_INITIALIZER("iva", true, 133000000,
OMAP4460_VDD_IVA_OPP50_UV),
+ /* IVA OPP2 - OPP100 */
+ OPP_INITIALIZER("iva", true, 266100000,
OMAP4460_VDD_IVA_OPP100_UV),
+ /*
+ * IVA OPP3 - OPP-Turbo + Disabled as the reference schematics
+ * recommends Phoenix VCORE2 which can supply only 600mA - so
the ones
+ * above this OPP frequency, even though OMAP is capable,
should be
+ * enabled by board file which is sure of the chip power
capability
+ */
+ OPP_INITIALIZER("iva", false, 332000000,
OMAP4460_VDD_IVA_OPPTURBO_UV),
+ /* IVA OPP4 - OPP-Nitro */
+ OPP_INITIALIZER("iva", false, 430000000,
OMAP4460_VDD_IVA_OPPNITRO_UV),
+ /* IVA OPP5 - OPP-Nitro SpeedBin*/
+ OPP_INITIALIZER("iva", false, 500000000,
OMAP4460_VDD_IVA_OPPNITRO_UV),
+
+ /* TODO: add DSP, aess, fdif, gpu */
+};
+
/**
* omap4_opp_init() - initialize omap4 opp table
*/
@@ -96,10 +172,12 @@ int __init omap4_opp_init(void)
if (!cpu_is_omap44xx())
return r;
-
- r = omap_init_opp_table(omap44xx_opp_def_list,
- ARRAY_SIZE(omap44xx_opp_def_list));
-
+ if (cpu_is_omap443x())
+ r = omap_init_opp_table(omap443x_opp_def_list,
+ ARRAY_SIZE(omap443x_opp_def_list));
+ else if (cpu_is_omap446x())
+ r = omap_init_opp_table(omap446x_opp_def_list,
+ ARRAY_SIZE(omap446x_opp_def_list));
return r;
}
device_initcall(omap4_opp_init);
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c
b/arch/arm/mach-omap2/voltagedomains44xx_data.c
index cb64996..f516cfe 100644
--- a/arch/arm/mach-omap2/voltagedomains44xx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -91,9 +91,17 @@ static int __init
omap44xx_voltage_early_init(void)
* XXX Will depend on the process, validation, and binning
* for the currently-running IC
*/
- omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data;
- omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data;
- omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data;
+ if (cpu_is_omap443x()) {
+ omap4_vdd_mpu_info.volt_data =
omap443x_vdd_mpu_volt_data;
+ omap4_vdd_iva_info.volt_data =
omap443x_vdd_iva_volt_data;
+ omap4_vdd_core_info.volt_data =
omap443x_vdd_core_volt_data;
+ } else if (cpu_is_omap446x()) {
+ omap4_vdd_mpu_info.volt_data =
omap446x_vdd_mpu_volt_data;
+ omap4_vdd_iva_info.volt_data =
omap446x_vdd_iva_volt_data;
+ omap4_vdd_core_info.volt_data =
omap446x_vdd_core_volt_data;
+ } else {
+ return -ENODATA;
+ }
return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
omap4_vdd_info,
--
1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Thiago A. Correa
2011-10-03 00:32:48 UTC
Permalink
This patch makes serial debug messages optional on
Samsung SoC s3c devices making all UART ports available
for other uses.

Signed-off-by: Thiago A. Correa <***@gmail.com>
---
arch/arm/boot/compressed/head.S | 2 +-
arch/arm/plat-samsung/Kconfig | 11 +++++++++++
arch/arm/plat-samsung/include/plat/uncompress.h | 9 +++++++++
3 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 9f5ac11..3afb755 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -58,7 +58,7 @@
add \rb, \rb, #0x00010000 @ Ser1
#endif
.endm
-#elif defined(CONFIG_ARCH_S3C2410)
+#elif defined(CONFIG_ARCH_S3C2410) && CONFIG_ENABLE_DEBUG_S3C_UART
.macro loadsp, rb, tmp
mov \rb, #0x50000000
add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index b3e1065..c2183f0 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -33,7 +33,17 @@ config S3C_BOOT_ERROR_RESET
Say y here to use the watchdog to reset the system if the
kernel decompressor detects an error during decompression.

+
+config ENABLE_DEBUG_S3C_UART
+ bool "Enable S3C Debug UART"
+ help
+ Say Y here if you want debug print of low level kernel messages
+ using S3C UARTS.
+
+ If in doubt, say N.
+
config S3C_BOOT_UART_FORCE_FIFO
+ depends on ENABLE_DEBUG_S3C_UART
bool "Force UART FIFO on during boot process"
default y
help
@@ -42,6 +52,7 @@ config S3C_BOOT_UART_FORCE_FIFO


config S3C_LOWLEVEL_UART_PORT
+ depends on ENABLE_DEBUG_S3C_UART
int "S3C UART to use for low-level messages"
default 0
help
diff --git a/arch/arm/plat-samsung/include/plat/uncompress.h b/arch/arm/plat-samsung/include/plat/uncompress.h
index ee48e12..778c2df 100644
--- a/arch/arm/plat-samsung/include/plat/uncompress.h
+++ b/arch/arm/plat-samsung/include/plat/uncompress.h
@@ -37,6 +37,7 @@ static void arch_detect_cpu(void);
/* how many bytes we allow into the FIFO at a time in FIFO mode */
#define FIFO_MAX (14)

+#if defined(CONFIG_ENABLE_DEBUG_S3C_UART)
#define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT)

static __inline__ void
@@ -85,11 +86,19 @@ static void putc(int ch)
/* write byte to transmission register */
uart_wr(S3C2410_UTXH, ch);
}
+#else
+static inline void putc(int ch)
+{
+}
+
+
+#endif

static inline void flush(void)
{
}

+
#define __raw_writel(d, ad) \
do { \
*((volatile unsigned int __force *)(ad)) = (d); \
--
1.7.3.4
Thiago A. Corrêa
2011-10-10 14:44:45 UTC
Permalink
Hi,

This was the first patch I have submited, would appreciate an Ack
or comments.

Kind Regards,
Thiago A. Correa
manjunath.goudar-QSEj5FYQhm4dnm+
2013-02-07 17:33:57 UTC
Permalink
From: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>


Separate the SOC On-Chip host controller driver from ehci-hcd
host code into its own driver module.

Manjunath Goudar (10):
USB:Changed omap2plus_defconfig to support OMAP USB static driver
USB: EHCI: make ehci-omap a separate driver
USB: EHCI: make ehci-spear a separate driver
USB: EHCI: make ehci-orion a separate driver
USB: EHCI: make ehci-atmel a separate driver
USB: EHCI: make ehci-s5p a separate driver
USB: EHCI: make ehci-mv a separate driver
USB: EHCI: make ehci-vt8500 a separate driver
USB: EHCI: make ehci-msm a separate driver
USB: EHCI: make ehci-w90X900 a separate driver

arch/arm/configs/omap2plus_defconfig | 4 ++
drivers/usb/host/Kconfig | 43 ++++++++++++---
drivers/usb/host/Makefile | 10 +++-
drivers/usb/host/ehci-atmel.c | 78 ++++++++++++++-------------
drivers/usb/host/ehci-hcd.c | 75 +++++++-------------------
drivers/usb/host/ehci-msm.c | 84 +++++++++++++----------------
drivers/usb/host/ehci-mv.c | 81 +++++++++++++---------------
drivers/usb/host/ehci-omap.c | 69 ++++++++++--------------
drivers/usb/host/ehci-orion.c | 98 +++++++++++++++++-----------------
drivers/usb/host/ehci-s5p.c | 69 +++++++++++++-----------
drivers/usb/host/ehci-spear.c | 77 +++++++++++++-------------
drivers/usb/host/ehci-vt8500.c | 73 ++++++++++++-------------
drivers/usb/host/ehci-w90x900.c | 90 ++++++++++++++-----------------
13 files changed, 415 insertions(+), 436 deletions(-)
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Ezequiel Garcia
2013-02-07 20:13:56 UTC
Permalink
Hi Manjunath,

Nice work.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
=20
=20
Separate the SOC On-Chip host controller driver from ehci-hcd
host code into its own driver module.
Perhaps you could add a few lines explaining why you're doing this.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
=20
USB:Changed omap2plus_defconfig to support OMAP USB static driver
USB: EHCI: make ehci-omap a separate driver
USB: EHCI: make ehci-spear a separate driver
USB: EHCI: make ehci-orion a separate driver
USB: EHCI: make ehci-atmel a separate driver
USB: EHCI: make ehci-s5p a separate driver
USB: EHCI: make ehci-mv a separate driver
USB: EHCI: make ehci-vt8500 a separate driver
USB: EHCI: make ehci-msm a separate driver
USB: EHCI: make ehci-w90X900 a separate driver
=20
arch/arm/configs/omap2plus_defconfig | 4 ++
drivers/usb/host/Kconfig | 43 ++++++++++++---
drivers/usb/host/Makefile | 10 +++-
drivers/usb/host/ehci-atmel.c | 78 ++++++++++++++----------=
---
Post by manjunath.goudar-QSEj5FYQhm4dnm+
drivers/usb/host/ehci-hcd.c | 75 +++++++-----------------=
--
Post by manjunath.goudar-QSEj5FYQhm4dnm+
drivers/usb/host/ehci-msm.c | 84 +++++++++++++-----------=
-----
Post by manjunath.goudar-QSEj5FYQhm4dnm+
drivers/usb/host/ehci-mv.c | 81 +++++++++++++-----------=
----
Post by manjunath.goudar-QSEj5FYQhm4dnm+
drivers/usb/host/ehci-omap.c | 69 ++++++++++--------------
drivers/usb/host/ehci-orion.c | 98 +++++++++++++++++-------=
----------
Post by manjunath.goudar-QSEj5FYQhm4dnm+
drivers/usb/host/ehci-s5p.c | 69 +++++++++++++-----------
drivers/usb/host/ehci-spear.c | 77 +++++++++++++-----------=
--
Post by manjunath.goudar-QSEj5FYQhm4dnm+
drivers/usb/host/ehci-vt8500.c | 73 ++++++++++++------------=
Alan Stern
2013-02-08 15:23:31 UTC
Permalink
Post by manjunath.goudar-QSEj5FYQhm4dnm+
Separate the SOC On-Chip host controller driver from ehci-hcd
host code into its own driver module.
USB:Changed omap2plus_defconfig to support OMAP USB static driver
USB: EHCI: make ehci-omap a separate driver
USB: EHCI: make ehci-spear a separate driver
USB: EHCI: make ehci-orion a separate driver
USB: EHCI: make ehci-atmel a separate driver
USB: EHCI: make ehci-s5p a separate driver
USB: EHCI: make ehci-mv a separate driver
USB: EHCI: make ehci-vt8500 a separate driver
USB: EHCI: make ehci-msm a separate driver
USB: EHCI: make ehci-w90X900 a separate driver
I'm going on vacation for a week, so I won't be able to review these
right away. If you want to submit updated patches based on feedback
from other people, go right ahead.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
manjunath.goudar-QSEj5FYQhm4dnm+
2013-02-07 17:33:58 UTC
Permalink
From: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>

Selected EHCI and OMAP driver as static drivers using omap2plus_defconfig
configuration

Signed-off-by: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>
Signed-off-by: Arnd Bergmann <arnd-QSEj5FYQhm4dnm+***@public.gmane.org>
Cc: Felipe Balbi <balbi-***@public.gmane.org>
Cc: Greg KH <greg-U8xfFu+***@public.gmane.org>
Cc: Alan Stern <stern-nwvwT67g6+6dFdvTe/***@public.gmane.org>
Cc: linux-usb-***@public.gmane.org
Cc: Tony Lindgren <tony-***@public.gmane.org>
---
arch/arm/configs/omap2plus_defconfig | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 82ce8d7..9ea7a9c 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -182,6 +182,10 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_SUSPEND=y
CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_HCD_OMAP=y
CONFIG_USB_WDM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_LIBUSUAL=y
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
manjunath.goudar-QSEj5FYQhm4dnm+
2013-02-07 17:33:59 UTC
Permalink
From: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>

Separate the OMAP host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>
Signed-off-by: Arnd Bergmann <arnd-QSEj5FYQhm4dnm+***@public.gmane.org>
Cc: Felipe Balbi <balbi-***@public.gmane.org>
Cc: Greg KH <greg-U8xfFu+***@public.gmane.org>
Cc: Alan Stern <stern-nwvwT67g6+6dFdvTe/***@public.gmane.org>
Cc: linux-usb-***@public.gmane.org
Cc: Tony Lindgren <tony-***@public.gmane.org>
---
drivers/usb/host/Kconfig | 2 +-
drivers/usb/host/Makefile | 2 +-
drivers/usb/host/ehci-hcd.c | 6 +---
drivers/usb/host/ehci-omap.c | 69 ++++++++++++++++++------------------------
4 files changed, 32 insertions(+), 47 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3a21c5d..11e102e 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -155,7 +155,7 @@ config USB_EHCI_MXC
Variation of ARC USB block used in some Freescale chips.

config USB_EHCI_HCD_OMAP
- bool "EHCI support for OMAP3 and later chips"
+ tristate "EHCI support for OMAP3 and later chips"
depends on USB_EHCI_HCD && ARCH_OMAP
default y
---help---
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 001fbff..b54a597 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -27,7 +27,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
-
+obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b416a3f..aaf93ca 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1252,11 +1252,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_sh_driver
#endif

-#ifdef CONFIG_USB_EHCI_HCD_OMAP
-#include "ehci-omap.c"
-#define PLATFORM_DRIVER ehci_hcd_omap_driver
-#endif
-
#ifdef CONFIG_PPC_PS3
#include "ehci-ps3.c"
#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
@@ -1347,6 +1342,7 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
!defined(PLATFORM_DRIVER) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index ac17a7c..9c10fc3 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -43,6 +43,11 @@
#include <linux/pm_runtime.h>
#include <linux/gpio.h>
#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>

#include <linux/platform_data/usb-omap.h>

@@ -58,9 +63,12 @@
#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0

/*-------------------------------------------------------------------------*/
+#include "ehci.h"

-static const struct hc_driver ehci_omap_hc_driver;
+#define DRIVER_DESC "EHCI OMAP driver"

+static const char hcd_name[] = "ehci-omap";
+static struct hc_driver __read_mostly ehci_omap_hc_driver;

static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
{
@@ -323,56 +331,37 @@ static struct platform_driver ehci_hcd_omap_driver = {
/*.suspend = ehci_hcd_omap_suspend, */
/*.resume = ehci_hcd_omap_resume, */
.driver = {
- .name = "ehci-omap",
+ .name = hcd_name,
}
};

-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ehci_omap_hc_driver = {
- .description = hcd_name,
- .product_desc = "OMAP-EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),

- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+static const struct ehci_driver_overrides omap_overrides __initdata = {
+ .reset = omap_ehci_init,
+};

- /*
- * basic lifecycle operations
- */
- .reset = omap_ehci_init,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
+static int __init ehci_omap_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;

- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);

- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
+ ehci_init_driver(&ehci_omap_hc_driver, &omap_overrides);
+ return platform_driver_register(&ehci_hcd_omap_driver);
+}
+module_init(ehci_omap_init);

- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
+static void __exit ehci_omap_cleanup(void)
+{
+ platform_driver_unregister(&ehci_hcd_omap_driver);
+}
+module_exit(ehci_omap_cleanup);

- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+MODULE_DESCRIPTION(DRIVER_DESC);

MODULE_ALIAS("platform:omap-ehci");
MODULE_AUTHOR("Texas Instruments, Inc.");
MODULE_AUTHOR("Felipe Balbi <felipe.balbi-***@public.gmane.org>");
+MODULE_LICENSE("GPL");
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Felipe Balbi
2013-02-08 07:42:29 UTC
Permalink
HI,
Post by manjunath.goudar-QSEj5FYQhm4dnm+
Separate the OMAP host controller driver from ehci-hcd host code
into its own driver module.
Alan and Roger have already been working on this for ehci-omap. Their
patches might already be in Greg's queue...
--
balbi
Roger Quadros
2013-02-08 08:56:32 UTC
Permalink
Post by Felipe Balbi
HI,
Post by manjunath.goudar-QSEj5FYQhm4dnm+
Separate the OMAP host controller driver from ehci-hcd host code
into its own driver module.
Alan and Roger have already been working on this for ehci-omap. Their
patches might already be in Greg's queue...
Manjunath,

ehci-omap will be taken care of so in [1] so you can please skip it
from your patches. Thanks.

cheers,
-roger

[1] https://patchwork.kernel.org/patch/2055131/
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
manjunath.goudar-QSEj5FYQhm4dnm+
2013-02-07 17:34:00 UTC
Permalink
From: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>

Separate the Spear host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>
Signed-off-by: Deepak Saxena <dsaxena-QSEj5FYQhm4dnm+***@public.gmane.org>
Cc: Greg KH <greg-U8xfFu+***@public.gmane.org>
Cc: Alan Stern <stern-nwvwT67g6+6dFdvTe/***@public.gmane.org>
Cc: Viresh Kumar <viresh.linux-***@public.gmane.org>
Cc: Shiraz Hashim <shiraz.hashim-***@public.gmane.org>
Cc: linux-usb-***@public.gmane.org
Cc: spear-devel-***@public.gmane.org
---
drivers/usb/host/Kconfig | 8 +++++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 6 +---
drivers/usb/host/ehci-spear.c | 77 ++++++++++++++++++++++-------------------
4 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 11e102e..4413075 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -162,6 +162,14 @@ config USB_EHCI_HCD_OMAP
Enables support for the on-chip EHCI controller on
OMAP3 and later chips.

+config USB_EHCI_HCD_SPEAR
+ tristate "Support for ST spear on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && PLAT_SPEAR
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ ST spear chips.
+
config USB_EHCI_MSM
bool "Support for MSM on-chip EHCI USB controller"
depends on USB_EHCI_HCD && ARCH_MSM
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index b54a597..c97f4ab 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
+obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index aaf93ca..68cea63 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1292,11 +1292,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER vt8500_ehci_driver
#endif

-#ifdef CONFIG_PLAT_SPEAR
-#include "ehci-spear.c"
-#define PLATFORM_DRIVER spear_ehci_hcd_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_MSM
#include "ehci-msm.c"
#define PLATFORM_DRIVER ehci_msm_driver
@@ -1343,6 +1338,7 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
!defined(PLATFORM_DRIVER) && \
!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
+ !IS_ENABLED(CONFIG_PLAT_SPEAR) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 466c1bb..6e42cee 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -11,11 +11,25 @@
* more details.
*/

+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+
+
#include <linux/clk.h>
#include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI spear driver"
+
+static const char hcd_name[] = "ehci-spear";

struct spear_ehci {
struct ehci_hcd ehci;
@@ -43,40 +57,7 @@ static int ehci_spear_setup(struct usb_hcd *hcd)

return ehci_setup(hcd);
}
-
-static const struct hc_driver ehci_spear_hc_driver = {
- .description = hcd_name,
- .product_desc = "SPEAr EHCI",
- .hcd_priv_size = sizeof(struct spear_ehci),
-
- /* generic hardware linkage */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /* basic lifecycle operations */
- .reset = ehci_spear_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /* managing i/o requests and associated device resources */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /* scheduling support */
- .get_frame_number = ehci_get_frame,
-
- /* root hub support */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static struct hc_driver __read_mostly ehci_spear_hc_driver;

#ifdef CONFIG_PM
static int ehci_spear_drv_suspend(struct device *dev)
@@ -209,11 +190,35 @@ static struct platform_driver spear_ehci_hcd_driver = {
.remove = spear_ehci_hcd_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
- .name = "spear-ehci",
+ .name = hcd_name,
.bus = &platform_bus_type,
.pm = &ehci_spear_pm_ops,
.of_match_table = of_match_ptr(spear_ehci_id_table),
}
};

-MODULE_ALIAS("platform:spear-ehci");
+
+static const struct ehci_driver_overrides spear_overrides __initdata = {
+ .reset = ehci_spear_setup,
+};
+
+static int __init ehci_spear_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_spear_hc_driver, &spear_overrides);
+ return platform_driver_register(&spear_ehci_hcd_driver);
+}
+module_init(ehci_spear_init);
+
+static void __exit ehci_spear_cleanup(void)
+{
+ platform_driver_unregister(&spear_ehci_hcd_driver);
+}
+module_exit(ehci_spear_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Viresh Kumar
2013-02-08 04:27:19 UTC
Permalink
Post by manjunath.goudar-QSEj5FYQhm4dnm+
Separate the Spear host controller driver from ehci-hcd host code
into its own driver module.
Please write spear as SPEAr everywhere, leaving
functions/variables/config options.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
---
drivers/usb/host/Kconfig | 8 +++++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 6 +---
drivers/usb/host/ehci-spear.c | 77 ++++++++++++++++++++++-------------------
4 files changed, 51 insertions(+), 41 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 11e102e..4413075 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -162,6 +162,14 @@ config USB_EHCI_HCD_OMAP
Enables support for the on-chip EHCI controller on
OMAP3 and later chips.
+config USB_EHCI_HCD_SPEAR
+ tristate "Support for ST spear on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && PLAT_SPEAR
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ ST spear chips.
+
config USB_EHCI_MSM
bool "Support for MSM on-chip EHCI USB controller"
depends on USB_EHCI_HCD && ARCH_MSM
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index b54a597..c97f4ab 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
+obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index aaf93ca..68cea63 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1292,11 +1292,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER vt8500_ehci_driver
#endif
-#ifdef CONFIG_PLAT_SPEAR
-#include "ehci-spear.c"
-#define PLATFORM_DRIVER spear_ehci_hcd_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_MSM
#include "ehci-msm.c"
#define PLATFORM_DRIVER ehci_msm_driver
@@ -1343,6 +1338,7 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
!defined(PLATFORM_DRIVER) && \
!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
+ !IS_ENABLED(CONFIG_PLAT_SPEAR) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 466c1bb..6e42cee 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -11,11 +11,25 @@
* more details.
*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+
+
remove these blank lines.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
#include <linux/clk.h>
#include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/dma-mapping.h>
Keep all of them in alphabetical order.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI spear driver"
+
+static const char hcd_name[] = "ehci-spear";
struct spear_ehci {
struct ehci_hcd ehci;
@@ -43,40 +57,7 @@ static int ehci_spear_setup(struct usb_hcd *hcd)
return ehci_setup(hcd);
}
-
-static const struct hc_driver ehci_spear_hc_driver = {
- .description = hcd_name,
- .product_desc = "SPEAr EHCI",
- .hcd_priv_size = sizeof(struct spear_ehci),
-
- /* generic hardware linkage */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /* basic lifecycle operations */
- .reset = ehci_spear_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /* managing i/o requests and associated device resources */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /* scheduling support */
- .get_frame_number = ehci_get_frame,
-
- /* root hub support */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static struct hc_driver __read_mostly ehci_spear_hc_driver;
#ifdef CONFIG_PM
static int ehci_spear_drv_suspend(struct device *dev)
@@ -209,11 +190,35 @@ static struct platform_driver spear_ehci_hcd_driver = {
.remove = spear_ehci_hcd_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
- .name = "spear-ehci",
+ .name = hcd_name,
.bus = &platform_bus_type,
.pm = &ehci_spear_pm_ops,
.of_match_table = of_match_ptr(spear_ehci_id_table),
}
};
-MODULE_ALIAS("platform:spear-ehci");
+
+static const struct ehci_driver_overrides spear_overrides __initdata = {
+ .reset = ehci_spear_setup,
+};
+
+static int __init ehci_spear_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_spear_hc_driver, &spear_overrides);
+ return platform_driver_register(&spear_ehci_hcd_driver);
+}
+module_init(ehci_spear_init);
+
+static void __exit ehci_spear_cleanup(void)
+{
+ platform_driver_unregister(&spear_ehci_hcd_driver);
+}
+module_exit(ehci_spear_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
manjunath.goudar-QSEj5FYQhm4dnm+
2013-02-07 17:34:01 UTC
Permalink
From: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>

Separate the Marvell Orion host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>
Cc: Greg KH <greg-U8xfFu+***@public.gmane.org>
Cc: Alan Stern <stern-nwvwT67g6+6dFdvTe/***@public.gmane.org>
Cc: Jason Cooper <jason-***@public.gmane.org>
Cc: Andrew Lunn <andrew-***@public.gmane.org>
Cc: Russell King <linux-lFZ/***@public.gmane.org>
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+***@public.gmane.org
Cc: linux-kernel-***@public.gmane.org
---
drivers/usb/host/Kconfig | 7 +++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 27 +++++-------
drivers/usb/host/ehci-orion.c | 98 +++++++++++++++++++++--------------------
4 files changed, 69 insertions(+), 64 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 4413075..3689b7b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -169,6 +169,13 @@ config USB_EHCI_HCD_SPEAR
---help---
Enables support for the on-chip EHCI controller on
ST spear chips.
+config USB_EHCI_HCD_ORION
+ tristate "Support for Marvell Orion on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && PLAT_ORION
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ Morvell Orion chips.

config USB_EHCI_MSM
bool "Support for MSM on-chip EHCI USB controller"
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index c97f4ab..23b07dd 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
+obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 68cea63..5a19a57 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -155,7 +155,7 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
* before driver shutdown. But it also seems to be caused by bugs in cardbus
* bridge shutdown: shutting down the bridge before the devices using it.
*/
-static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+int handshake(struct ehci_hcd *ehci, void __iomem *ptr,
u32 mask, u32 done, int usec)
{
u32 result;
@@ -172,9 +172,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
} while (usec > 0);
return -ETIMEDOUT;
}
-
+EXPORT_SYMBOL_GPL(handshake);
/* check TDI/ARC silicon is in host mode */
-static int tdi_in_host_mode (struct ehci_hcd *ehci)
+static int tdi_in_host_mode(struct ehci_hcd *ehci)
{
u32 tmp;

@@ -186,7 +186,7 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
* Force HC to halt state from unknown (EHCI spec section 2.3).
* Must be called with interrupts enabled and the lock not held.
*/
-static int ehci_halt (struct ehci_hcd *ehci)
+int ehci_halt(struct ehci_hcd *ehci)
{
u32 temp;

@@ -215,9 +215,9 @@ static int ehci_halt (struct ehci_hcd *ehci)
return handshake(ehci, &ehci->regs->status,
STS_HALT, STS_HALT, 16 * 125);
}
-
+EXPORT_SYMBOL_GPL(ehci_halt);
/* put TDI/ARC silicon into EHCI mode */
-static void tdi_reset (struct ehci_hcd *ehci)
+void tdi_reset(struct ehci_hcd *ehci)
{
u32 tmp;

@@ -231,12 +231,12 @@ static void tdi_reset (struct ehci_hcd *ehci)
tmp |= USBMODE_BE;
ehci_writel(ehci, tmp, &ehci->regs->usbmode);
}
-
+EXPORT_SYMBOL_GPL(tdi_reset);
/*
* Reset a non-running (STS_HALT == 1) controller.
* Must be called with interrupts enabled and the lock not held.
*/
-static int ehci_reset (struct ehci_hcd *ehci)
+int ehci_reset(struct ehci_hcd *ehci)
{
int retval;
u32 command = ehci_readl(ehci, &ehci->regs->command);
@@ -272,7 +272,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
ehci->resuming_ports = 0;
return retval;
}
-
+EXPORT_SYMBOL_GPL(ehci_reset);
/*
* Idle the controller (turn off the schedules).
* Must be called with interrupts enabled and the lock not held.
@@ -352,7 +352,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
* This forcibly disables dma and IRQs, helping kexec and other cases
* where the next system software may expect clean state.
*/
-static void ehci_shutdown(struct usb_hcd *hcd)
+void ehci_shutdown(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);

@@ -366,7 +366,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)

hrtimer_cancel(&ehci->hrtimer);
}
-
+EXPORT_SYMBOL_GPL(ehci_shutdown);
/*-------------------------------------------------------------------------*/

/*
@@ -1267,11 +1267,6 @@ MODULE_LICENSE ("GPL");
#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
#endif

-#ifdef CONFIG_PLAT_ORION
-#include "ehci-orion.c"
-#define PLATFORM_DRIVER ehci_orion_driver
-#endif
-
#ifdef CONFIG_USB_W90X900_EHCI
#include "ehci-w90x900.c"
#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 914a3ec..de4dde2 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -8,6 +8,17 @@
* warranty of any kind, whether express or implied.
*/

+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+
+#include <linux/slab.h>
+#include <linux/usb/ulpi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/gpio.h>
+
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -17,6 +28,9 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
+#include <linux/dma-mapping.h>
+#include "ehci.h"
+

#define rdl(off) __raw_readl(hcd->regs + (off))
#define wrl(off, val) __raw_writel((val), hcd->regs + (off))
@@ -34,6 +48,17 @@
#define USB_PHY_IVREF_CTRL 0x440
#define USB_PHY_TST_GRP_CTRL 0x450

+#define DRIVER_DESC "EHCI orion driver"
+
+static const char hcd_name[] = "ehci-orion";
+
+static struct hc_driver __read_mostly ehci_orion_hc_driver;
+
+static const struct ehci_driver_overrides orion_overrides __initdata = {
+ .reset = ehci_setup,
+};
+
+
/*
* Implement Orion USB controller specification guidelines
*/
@@ -104,51 +129,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
wrl(USB_MODE, 0x13);
}

-static const struct hc_driver ehci_orion_hc_driver = {
- .description = hcd_name,
- .product_desc = "Marvell Orion EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
static void
ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
const struct mbus_dram_target_info *dram)
@@ -323,8 +303,6 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
return 0;
}

-MODULE_ALIAS("platform:orion-ehci");
-
static const struct of_device_id ehci_orion_dt_ids[] = {
{ .compatible = "marvell,orion-ehci", },
{},
@@ -336,8 +314,32 @@ static struct platform_driver ehci_orion_driver = {
.remove = __exit_p(ehci_orion_drv_remove),
.shutdown = usb_hcd_platform_shutdown,
.driver = {
- .name = "orion-ehci",
+ .name = hcd_name,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(ehci_orion_dt_ids),
},
};
+
+static int __init ehci_orion_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_orion_hc_driver, &orion_overrides);
+ return platform_driver_register(&ehci_orion_driver);
+}
+module_init(ehci_orion_init);
+
+static void __exit ehci_orion_cleanup(void)
+{
+ platform_driver_unregister(&ehci_orion_driver);
+}
+module_exit(ehci_orion_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:ehci-orion");
+MODULE_AUTHOR("Tzachi Perelstein");
+MODULE_LICENSE("GPL");
+
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Arnd Bergmann
2013-02-07 19:41:22 UTC
Permalink
Post by manjunath.goudar-QSEj5FYQhm4dnm+
@@ -155,7 +155,7 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
* before driver shutdown. But it also seems to be caused by bugs in cardbus
* bridge shutdown: shutting down the bridge before the devices using it.
*/
-static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+int handshake(struct ehci_hcd *ehci, void __iomem *ptr,
u32 mask, u32 done, int usec)
{
u32 result;
I had not noticed this before, but apparently it belongs into the
tegra patch that you dropped, rather than this patch.

Same thing for all the changes below.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
@@ -172,9 +172,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
} while (usec > 0);
return -ETIMEDOUT;
}
-
+EXPORT_SYMBOL_GPL(handshake);
/* check TDI/ARC silicon is in host mode */
-static int tdi_in_host_mode (struct ehci_hcd *ehci)
+static int tdi_in_host_mode(struct ehci_hcd *ehci)
{
u32 tmp;
@@ -186,7 +186,7 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
* Force HC to halt state from unknown (EHCI spec section 2.3).
* Must be called with interrupts enabled and the lock not held.
*/
-static int ehci_halt (struct ehci_hcd *ehci)
+int ehci_halt(struct ehci_hcd *ehci)
{
u32 temp;
@@ -215,9 +215,9 @@ static int ehci_halt (struct ehci_hcd *ehci)
return handshake(ehci, &ehci->regs->status,
STS_HALT, STS_HALT, 16 * 125);
}
-
+EXPORT_SYMBOL_GPL(ehci_halt);
/* put TDI/ARC silicon into EHCI mode */
-static void tdi_reset (struct ehci_hcd *ehci)
+void tdi_reset(struct ehci_hcd *ehci)
{
u32 tmp;
@@ -231,12 +231,12 @@ static void tdi_reset (struct ehci_hcd *ehci)
tmp |= USBMODE_BE;
ehci_writel(ehci, tmp, &ehci->regs->usbmode);
}
-
+EXPORT_SYMBOL_GPL(tdi_reset);
/*
* Reset a non-running (STS_HALT == 1) controller.
* Must be called with interrupts enabled and the lock not held.
*/
-static int ehci_reset (struct ehci_hcd *ehci)
+int ehci_reset(struct ehci_hcd *ehci)
{
int retval;
u32 command = ehci_readl(ehci, &ehci->regs->command);
@@ -272,7 +272,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
ehci->resuming_ports = 0;
return retval;
}
-
+EXPORT_SYMBOL_GPL(ehci_reset);
/*
* Idle the controller (turn off the schedules).
* Must be called with interrupts enabled and the lock not held.
@@ -352,7 +352,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
* This forcibly disables dma and IRQs, helping kexec and other cases
* where the next system software may expect clean state.
*/
-static void ehci_shutdown(struct usb_hcd *hcd)
+void ehci_shutdown(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -366,7 +366,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)
hrtimer_cancel(&ehci->hrtimer);
}
-
+EXPORT_SYMBOL_GPL(ehci_shutdown);
Arnd
Florian Fainelli
2013-02-08 10:38:02 UTC
Permalink
Hello Manjunath,
Post by manjunath.goudar-QSEj5FYQhm4dnm+
Separate the Marvell Orion host controller driver from ehci-hcd host code
into its own driver module.
[snip]

The changes you introduce in ehci-hcd.c would certainly deserve their
own preliminary patch in this serie and not be squashed into this one imho.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -155,7 +155,7 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
* before driver shutdown. But it also seems to be caused by bugs in cardbus
* bridge shutdown: shutting down the bridge before the devices using it.
*/
-static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+int handshake(struct ehci_hcd *ehci, void __iomem *ptr,
u32 mask, u32 done, int usec)
{
u32 result;
@@ -172,9 +172,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
} while (usec > 0);
return -ETIMEDOUT;
}
-
+EXPORT_SYMBOL_GPL(handshake);
This sounds way too generic as a name to be exported as is, so please
namespace this with ehci_hcd_ at least.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
/* check TDI/ARC silicon is in host mode */
-static int tdi_in_host_mode (struct ehci_hcd *ehci)
+static int tdi_in_host_mode(struct ehci_hcd *ehci)
Looks unrelated to the goals of your patches.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
{
u32 tmp;
@@ -186,7 +186,7 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
* Force HC to halt state from unknown (EHCI spec section 2.3).
* Must be called with interrupts enabled and the lock not held.
*/
-static int ehci_halt (struct ehci_hcd *ehci)
+int ehci_halt(struct ehci_hcd *ehci)
{
u32 temp;
@@ -215,9 +215,9 @@ static int ehci_halt (struct ehci_hcd *ehci)
return handshake(ehci, &ehci->regs->status,
STS_HALT, STS_HALT, 16 * 125);
}
-
+EXPORT_SYMBOL_GPL(ehci_halt);
I would rename this to ehci_hcd_halt to express the fact that it takes
an ehci_hcd structure pointer as parameter, can be addressed later.
Post by manjunath.goudar-QSEj5FYQhm4dnm+
/* put TDI/ARC silicon into EHCI mode */
-static void tdi_reset (struct ehci_hcd *ehci)
+void tdi_reset(struct ehci_hcd *ehci)
{
u32 tmp;
@@ -231,12 +231,12 @@ static void tdi_reset (struct ehci_hcd *ehci)
tmp |= USBMODE_BE;
ehci_writel(ehci, tmp, &ehci->regs->usbmode);
}
-
+EXPORT_SYMBOL_GPL(tdi_reset);
Same here, way too generic to be exported as is as a symbol name.
--
Florian
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
manjunath.goudar-QSEj5FYQhm4dnm+
2013-02-07 17:34:03 UTC
Permalink
From: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>

Separate the s5p host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar-QSEj5FYQhm4dnm+***@public.gmane.org>
Cc: Greg KH <greg-U8xfFu+***@public.gmane.org>
Cc: Alan Stern <stern-nwvwT67g6+6dFdvTe/***@public.gmane.org>
Cc: Kukjin Kim <kgene.kim-***@public.gmane.org>
Cc: Kyungmin Park <kyungmin.park-***@public.gmane.org>
Cc: Grant Likely <grant.likely-s3s/***@public.gmane.org>
Cc: Rob Herring <rob.herring-bsGFqQB8/***@public.gmane.org>
Cc: linux-usb-***@public.gmane.org
---
drivers/usb/host/Kconfig | 2 +-
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 6 +---
drivers/usb/host/ehci-s5p.c | 69 +++++++++++++++++++++++--------------------
4 files changed, 40 insertions(+), 38 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 5a13f9d..f2e0ed3 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -221,7 +221,7 @@ config USB_EHCI_SH
If you use the PCI EHCI controller, this option is not necessary.

config USB_EHCI_S5P
- boolean "S5P EHCI support"
+ tristate "S5P EHCI support"
depends on USB_EHCI_HCD && PLAT_S5P
help
Enable support for the S5P SOC's on-chip EHCI controller.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 96b4839..5c4f5e1 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
+obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 628ed139..36557e3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1297,11 +1297,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_msp_driver
#endif

-#ifdef CONFIG_USB_EHCI_TEGRA
-#include "ehci-tegra.c"
-#define PLATFORM_DRIVER tegra_ehci_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_S5P
#include "ehci-s5p.c"
#define PLATFORM_DRIVER s5p_ehci_driver
@@ -1330,6 +1325,7 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
!IS_ENABLED(CONFIG_PLAT_SPEAR) && \
!IS_ENABLED(CONFIG_ARCH_AT91) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_S5P) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 319dcfa..653e096 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -18,6 +18,16 @@
#include <linux/of_gpio.h>
#include <linux/platform_data/usb-ehci-s5p.h>
#include <plat/usb-phy.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI s5p driver"

#define EHCI_INSNREG00(base) (base + 0x90)
#define EHCI_INSNREG00_ENA_INCR16 (0x1 << 25)
@@ -28,43 +38,16 @@
(EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 | \
EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN)

+static const char hcd_name[] = "ehci-s5p";
+static struct hc_driver __read_mostly s5p_ehci_hc_driver;
+
+
struct s5p_ehci_hcd {
struct device *dev;
struct usb_hcd *hcd;
struct clk *clk;
};

-static const struct hc_driver s5p_ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "S5P EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- .reset = ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- .get_frame_number = ehci_get_frame,
-
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
static void s5p_setup_vbus_gpio(struct platform_device *pdev)
{
int err;
@@ -283,5 +266,27 @@ static struct platform_driver s5p_ehci_driver = {
.of_match_table = of_match_ptr(exynos_ehci_match),
}
};
+static const struct ehci_driver_overrides s5p_overrides __initdata = {
+ .reset = ehci_setup,
+};
+
+static int __init ehci_s5p_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&s5p_ehci_hc_driver, &s5p_overrides);
+ return platform_driver_register(&s5p_ehci_driver);
+}
+module_init(ehci_s5p_init);
+
+static void __exit ehci_s5p_cleanup(void)
+{
+ platform_driver_unregister(&s5p_ehci_driver);
+}
+module_exit(ehci_s5p_cleanup);

-MODULE_ALIAS("platform:s5p-ehci");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:ehci-s5p");
+MODULE_LICENSE("GPL");
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Stephen Warren
2013-02-07 18:49:42 UTC
Permalink
Post by manjunath.goudar-QSEj5FYQhm4dnm+
Separate the s5p host controller driver from ehci-hcd host code
into its own driver module.
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
@@ -1297,11 +1297,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_msp_driver
#endif
-#ifdef CONFIG_USB_EHCI_TEGRA
-#include "ehci-tegra.c"
-#define PLATFORM_DRIVER tegra_ehci_driver
-#endif
-
That also looks wrong.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
m***@linaro.org
2013-02-07 17:34:04 UTC
Permalink
From: Manjunath Goudar <***@linaro.org>

Separate the mv(marvell) host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <***@linaro.org>
Cc: Greg KH <***@kroah.com>
Cc: Alan Stern <***@rowland.harvard.edu>
Cc: Jason Cooper <***@lakedaemon.net>
Cc: Andrew Lunn <***@lunn.ch>
Cc: linux-***@vger.kernel.org
Cc: linux-***@vger.kernel.org
---
drivers/usb/host/Kconfig | 2 +-
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 6 +---
drivers/usb/host/ehci-mv.c | 81 ++++++++++++++++++++-----------------------
4 files changed, 40 insertions(+), 50 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f2e0ed3..e7c3ce0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -227,7 +227,7 @@ config USB_EHCI_S5P
Enable support for the S5P SOC's on-chip EHCI controller.

config USB_EHCI_MV
- bool "EHCI support for Marvell on-chip controller"
+ tristate "EHCI support for Marvell on-chip controller"
depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP)
select USB_EHCI_ROOT_HUB_TT
---help---
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 5c4f5e1..677f1d3 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
+obj-$(CONFIG_USB_EHCI_MV) += ehci-mv.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 36557e3..e636719 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1307,11 +1307,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_grlib_driver
#endif

-#ifdef CONFIG_USB_EHCI_MV
-#include "ehci-mv.c"
-#define PLATFORM_DRIVER ehci_mv_driver
-#endif
-
#ifdef CONFIG_MIPS_SEAD3
#include "ehci-sead3.c"
#define PLATFORM_DRIVER ehci_hcd_sead3_driver
@@ -1326,6 +1321,7 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_PLAT_SPEAR) && \
!IS_ENABLED(CONFIG_ARCH_AT91) && \
!IS_ENABLED(CONFIG_USB_EHCI_S5P) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_MV) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 6c56297..67de419 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -17,7 +17,18 @@
#include <linux/usb/otg.h>
#include <linux/platform_data/mv_usb.h>

+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI mv driver"
+
#define CAPLENGTH_MASK (0xff)
+static const char hcd_name[] = "ehci-mv";
+static struct hc_driver __read_mostly mv_ehci_hc_driver;

struct ehci_hcd_mv {
struct usb_hcd *hcd;
@@ -95,48 +106,6 @@ static int mv_ehci_reset(struct usb_hcd *hcd)
return retval;
}

-static const struct hc_driver mv_ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "Marvell EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = mv_ehci_reset,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-};
-
static int mv_ehci_probe(struct platform_device *pdev)
{
struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
@@ -302,7 +271,6 @@ static int mv_ehci_remove(struct platform_device *pdev)
{
struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
struct usb_hcd *hcd = ehci_mv->hcd;
- int clk_i;

if (hcd->rh_registered)
usb_remove_hcd(hcd);
@@ -351,8 +319,33 @@ static struct platform_driver ehci_mv_driver = {
.remove = mv_ehci_remove,
.shutdown = mv_ehci_shutdown,
.driver = {
- .name = "mv-ehci",
+ .name = hcd_name,
.bus = &platform_bus_type,
},
.id_table = ehci_id_table,
};
+static const struct ehci_driver_overrides mv_overrides __initdata = {
+ .reset = mv_ehci_reset,
+};
+
+static int __init ehci_mv_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&mv_ehci_hc_driver, &mv_overrides);
+ return platform_driver_register(&ehci_mv_driver);
+}
+module_init(ehci_mv_init);
+
+static void __exit ehci_mv_cleanup(void)
+{
+ platform_driver_unregister(&ehci_mv_driver);
+}
+module_exit(ehci_mv_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:ehci-mv");
+MODULE_AUTHOR("Marvell");
+MODULE_LICENSE("GPL");
--
1.7.9.5
m***@linaro.org
2013-02-07 17:34:02 UTC
Permalink
From: Manjunath Goudar <***@linaro.org>

Separate the Atmel host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <***@linaro.org>
Cc: Alan Stern <***@rowland.harvard.edu>
Cc: Greg KH <***@kroah.com>
Cc: Grant Likely <***@secretlab.ca>
Cc: Rob Herring <***@calxeda.com>
Cc: Andrew Victor <***@maxim.org.za>
Cc: Nicolas Ferre <***@atmel.com>
Cc: Jean-Christophe Plagniol-Villard <***@jcrosoft.com>
Cc: linux-***@vger.kernel.org
Cc: linux-***@vger.kernel.org
---
drivers/usb/host/Kconfig | 7 ++++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-atmel.c | 78 ++++++++++++++++++++++-------------------
drivers/usb/host/ehci-hcd.c | 6 +---
4 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3689b7b..5a13f9d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -176,6 +176,13 @@ config USB_EHCI_HCD_ORION
---help---
Enables support for the on-chip EHCI controller on
Morvell Orion chips.
+config USB_EHCI_HCD_AT91
+ tristate "Support for Atmel on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && ARCH_AT91
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ Atmel chips.

config USB_EHCI_MSM
bool "Support for MSM on-chip EHCI USB controller"
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 23b07dd..96b4839 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
+obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 27639487..2f06711 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -15,6 +15,19 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI atmel driver"
+
+static const char hcd_name[] = "ehci-atmel";
+static struct hc_driver __read_mostly ehci_atmel_hc_driver;

/* interface and function clocks */
static struct clk *iclk, *fclk;
@@ -60,41 +73,6 @@ static int ehci_atmel_setup(struct usb_hcd *hcd)
return ehci_setup(hcd);
}

-static const struct hc_driver ehci_atmel_hc_driver = {
- .description = hcd_name,
- .product_desc = "Atmel EHCI UHP HS",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /* generic hardware linkage */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /* basic lifecycle operations */
- .reset = ehci_atmel_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /* managing i/o requests and associated device resources */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /* scheduling support */
- .get_frame_number = ehci_get_frame,
-
- /* root hub support */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);

static int ehci_atmel_drv_probe(struct platform_device *pdev)
@@ -210,7 +188,35 @@ static struct platform_driver ehci_atmel_driver = {
.remove = ehci_atmel_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
- .name = "atmel-ehci",
+ .name = hcd_name,
.of_match_table = of_match_ptr(atmel_ehci_dt_ids),
},
};
+
+static const struct ehci_driver_overrides atmel_overrides __initdata = {
+ .reset = ehci_atmel_setup,
+};
+
+static int __init ehci_atmel_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&ehci_atmel_hc_driver, &atmel_overrides);
+ return platform_driver_register(&ehci_atmel_driver);
+}
+module_init(ehci_atmel_init);
+
+static void __exit ehci_atmel_cleanup(void)
+{
+ platform_driver_unregister(&ehci_atmel_driver);
+}
+module_exit(ehci_atmel_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_ALIAS("platform:ehci-atmel");
+MODULE_AUTHOR("Nicolas Ferre");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5a19a57..628ed139 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1272,11 +1272,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
#endif

-#ifdef CONFIG_ARCH_AT91
-#include "ehci-atmel.c"
-#define PLATFORM_DRIVER ehci_atmel_driver
-#endif
-
#ifdef CONFIG_USB_OCTEON_EHCI
#include "ehci-octeon.c"
#define PLATFORM_DRIVER ehci_octeon_driver
@@ -1334,6 +1329,7 @@ MODULE_LICENSE ("GPL");
!defined(PLATFORM_DRIVER) && \
!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
!IS_ENABLED(CONFIG_PLAT_SPEAR) && \
+ !IS_ENABLED(CONFIG_ARCH_AT91) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
--
1.7.9.5
Bo Shen
2013-02-08 02:58:40 UTC
Permalink
Hi Manjunath Goudar,
I test this patch based on linux master branch, the commit id is:
6bacaa9ddacb71c691d32c678d37bc59ffc71fac. (I am not sure this is the
right place for testing).
First, it has an compile error as following. After fix it, and
tested, the EHCI doesn't work.
---<8---
drivers/usb/host/ehci-atmel.c: In function 'ehci_atmel_drv_remove':
drivers/usb/host/ehci-atmel.c:167: error: implicit declaration of
function 'ehci_shutdown'
--->8---

And a little code style comments as following.
Post by m***@linaro.org
Separate the Atmel host controller driver from ehci-hcd host code
into its own driver module.
---
drivers/usb/host/Kconfig | 7 ++++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-atmel.c | 78 ++++++++++++++++++++++-------------------
drivers/usb/host/ehci-hcd.c | 6 +---
4 files changed, 51 insertions(+), 41 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3689b7b..5a13f9d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -176,6 +176,13 @@ config USB_EHCI_HCD_ORION
---help---
Enables support for the on-chip EHCI controller on
Morvell Orion chips.
Need blank line here.
Post by m***@linaro.org
+config USB_EHCI_HCD_AT91
+ tristate "Support for Atmel on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && ARCH_AT91
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ Atmel chips.
config USB_EHCI_MSM
bool "Support for MSM on-chip EHCI USB controller"
[snip]
Post by m***@linaro.org
+static void __exit ehci_atmel_cleanup(void)
+{
+ platform_driver_unregister(&ehci_atmel_driver);
+}
+module_exit(ehci_atmel_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_ALIAS("platform:ehci-atmel");
+MODULE_AUTHOR("Nicolas Ferre");
+MODULE_LICENSE("GPL");
+
Remove the blank line here. As to it is the EOF.

Best Regards,
Bo Shen
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Jean-Christophe PLAGNIOL-VILLARD
2013-06-12 11:53:41 UTC
Permalink
Post by m***@linaro.org
Separate the Atmel host controller driver from ehci-hcd host code
into its own driver module.
Acked-by: Jean-Christophe PLAGNIOL-VILLARD <***@jcrosoft.com>

Best Regards,
J.
Post by m***@linaro.org
---
drivers/usb/host/Kconfig | 7 ++++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-atmel.c | 78 ++++++++++++++++++++++-------------------
drivers/usb/host/ehci-hcd.c | 6 +---
4 files changed, 51 insertions(+), 41 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3689b7b..5a13f9d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -176,6 +176,13 @@ config USB_EHCI_HCD_ORION
---help---
Enables support for the on-chip EHCI controller on
Morvell Orion chips.
+config USB_EHCI_HCD_AT91
+ tristate "Support for Atmel on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && ARCH_AT91
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ Atmel chips.
config USB_EHCI_MSM
bool "Support for MSM on-chip EHCI USB controller"
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 23b07dd..96b4839 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
+obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 27639487..2f06711 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -15,6 +15,19 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI atmel driver"
+
+static const char hcd_name[] = "ehci-atmel";
+static struct hc_driver __read_mostly ehci_atmel_hc_driver;
/* interface and function clocks */
static struct clk *iclk, *fclk;
@@ -60,41 +73,6 @@ static int ehci_atmel_setup(struct usb_hcd *hcd)
return ehci_setup(hcd);
}
-static const struct hc_driver ehci_atmel_hc_driver = {
- .description = hcd_name,
- .product_desc = "Atmel EHCI UHP HS",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /* generic hardware linkage */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /* basic lifecycle operations */
- .reset = ehci_atmel_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /* managing i/o requests and associated device resources */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /* scheduling support */
- .get_frame_number = ehci_get_frame,
-
- /* root hub support */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
static int ehci_atmel_drv_probe(struct platform_device *pdev)
@@ -210,7 +188,35 @@ static struct platform_driver ehci_atmel_driver = {
.remove = ehci_atmel_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
- .name = "atmel-ehci",
+ .name = hcd_name,
.of_match_table = of_match_ptr(atmel_ehci_dt_ids),
},
};
+
+static const struct ehci_driver_overrides atmel_overrides __initdata = {
+ .reset = ehci_atmel_setup,
+};
+
+static int __init ehci_atmel_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&ehci_atmel_hc_driver, &atmel_overrides);
+ return platform_driver_register(&ehci_atmel_driver);
+}
+module_init(ehci_atmel_init);
+
+static void __exit ehci_atmel_cleanup(void)
+{
+ platform_driver_unregister(&ehci_atmel_driver);
+}
+module_exit(ehci_atmel_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_ALIAS("platform:ehci-atmel");
+MODULE_AUTHOR("Nicolas Ferre");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5a19a57..628ed139 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1272,11 +1272,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
#endif
-#ifdef CONFIG_ARCH_AT91
-#include "ehci-atmel.c"
-#define PLATFORM_DRIVER ehci_atmel_driver
-#endif
-
#ifdef CONFIG_USB_OCTEON_EHCI
#include "ehci-octeon.c"
#define PLATFORM_DRIVER ehci_octeon_driver
@@ -1334,6 +1329,7 @@ MODULE_LICENSE ("GPL");
!defined(PLATFORM_DRIVER) && \
!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
!IS_ENABLED(CONFIG_PLAT_SPEAR) && \
+ !IS_ENABLED(CONFIG_ARCH_AT91) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
--
1.7.9.5
m***@linaro.org
2013-02-07 17:34:07 UTC
Permalink
From: Manjunath Goudar <***@linaro.org>

Separate the Nuvoton On-Chip host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <***@linaro.org>
Cc: Greg KH <***@kroah.com>
Cc: Alan Stern <***@rowland.harvard.edu>
Cc: Wan ZongShun <***@gmail.com>
Cc: linux-***@vger.kernel.org
Cc: linux-***@vger.kernel.org
---
drivers/usb/host/Kconfig | 2 +-
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 6 +--
drivers/usb/host/ehci-w90x900.c | 90 +++++++++++++++++----------------------
4 files changed, 43 insertions(+), 56 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 8d18a6c..1b5e30b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -245,7 +245,7 @@ config USB_EHCI_MV
only be EHCI host. OTG is controller that can switch to host mode.

config USB_W90X900_EHCI
- bool "W90X900(W90P910) EHCI support"
+ tristate "W90X900(W90P910) EHCI support"
depends on USB_EHCI_HCD && ARCH_W90X900
---help---
Enables support for the W90X900 USB controller
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 6c1d0e0..74db4d4 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
obj-$(CONFIG_USB_EHCI_MV) += ehci-mv.o
obj-$(CONFIG_USB_EHCI_HCD_VT8500)+= ehci-vt8500.o
obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
+obj-$(CONFIG_USB_W90X900_EHCI) += ehci-w90x900.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d44115b..84ed7d7 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1267,11 +1267,6 @@ MODULE_LICENSE ("GPL");
#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
#endif

-#ifdef CONFIG_USB_W90X900_EHCI
-#include "ehci-w90x900.c"
-#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
-#endif
-
#ifdef CONFIG_USB_OCTEON_EHCI
#include "ehci-octeon.c"
#define PLATFORM_DRIVER ehci_octeon_driver
@@ -1314,6 +1309,7 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_USB_EHCI_MV) && \
!IS_ENABLED(CONFIG_ARCH_VT8500) && \
!IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
+ !IS_ENABLED(CONFIG_USB_W90X900_EHCI) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
index 59e0e24..0b677ec 100644
--- a/drivers/usb/host/ehci-w90x900.c
+++ b/drivers/usb/host/ehci-w90x900.c
@@ -13,11 +13,31 @@

#include <linux/platform_device.h>

+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include "ehci.h"
+
/* enable phy0 and phy1 for w90p910 */
#define ENPHY (0x01<<8)
#define PHY0_CTR (0xA4)
#define PHY1_CTR (0xA8)

+#define DRIVER_DESC "Nuvoton w90x900 On-Chip EHCI Host driver"
+
+static const char hcd_name[] = "ehci-w90x900";
+
+static struct hc_driver __read_mostly ehci_w90x900_hc_driver;
+
+static const struct ehci_driver_overrides ehci_w90X900_overrides __initdata = {
+ .reset = ehci_setup,
+};
+
static int usb_w90x900_probe(const struct hc_driver *driver,
struct platform_device *pdev)
{
@@ -99,54 +119,6 @@ void usb_w90x900_remove(struct usb_hcd *hcd, struct platform_device *pdev)
usb_put_hcd(hcd);
}

-static const struct hc_driver ehci_w90x900_hc_driver = {
- .description = hcd_name,
- .product_desc = "Nuvoton w90x900 EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_USB2|HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_setup,
- .start = ehci_run,
-
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-#endif
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
static int ehci_w90x900_probe(struct platform_device *pdev)
{
if (usb_disabled())
@@ -168,12 +140,30 @@ static struct platform_driver ehci_hcd_w90x900_driver = {
.probe = ehci_w90x900_probe,
.remove = ehci_w90x900_remove,
.driver = {
- .name = "w90x900-ehci",
+ .name = hcd_name,
.owner = THIS_MODULE,
},
};

+static int __init ehci_w90X900_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_w90x900_hc_driver, &ehci_w90X900_overrides);
+ return platform_driver_register(&ehci_hcd_w90x900_driver);
+}
+module_init(ehci_w90X900_init);
+
+static void __exit ehci_w90X900_cleanup(void)
+{
+ platform_driver_unregister(&ehci_hcd_w90x900_driver);
+}
+module_exit(ehci_w90X900_cleanup);
+
MODULE_AUTHOR("Wan ZongShun <***@gmail.com>");
-MODULE_DESCRIPTION("w90p910 usb ehci driver!");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:w90p910-ehci");
--
1.7.9.5
m***@linaro.org
2013-02-07 17:34:05 UTC
Permalink
From: Manjunath Goudar <***@linaro.org>

Separate the vt8500 host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <***@linaro.org>
Cc: Greg KH <***@kroah.com>
Cc: Alan Stern <***@rowland.harvard.edu>
Cc: Tony Prisk <***@prisktech.co.nz>
Cc: Alexey Charkov <***@gmail.com>
Cc: linux-***@vger.kernel.org
Cc: linux-***@vger.kernel.org
---
drivers/usb/host/Kconfig | 8 +++++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 5 ---
drivers/usb/host/ehci-vt8500.c | 73 ++++++++++++++++++----------------------
4 files changed, 42 insertions(+), 45 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index e7c3ce0..d20d22c 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -162,6 +162,14 @@ config USB_EHCI_HCD_OMAP
Enables support for the on-chip EHCI controller on
OMAP3 and later chips.

+config USB_EHCI_HCD_VT8500
+ tristate "Support for VT8500 on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && ARCH_VT8500
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ VT8500 chips.
+
config USB_EHCI_HCD_SPEAR
tristate "Support for ST spear on-chip EHCI USB controller"
depends on USB_EHCI_HCD && PLAT_SPEAR
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 677f1d3..cf71e5d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
obj-$(CONFIG_USB_EHCI_MV) += ehci-mv.o
+obj-$(CONFIG_USB_EHCI_HCD_VT8500)+= ehci-vt8500.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e636719..952f85e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1277,11 +1277,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_octeon_driver
#endif

-#ifdef CONFIG_ARCH_VT8500
-#include "ehci-vt8500.c"
-#define PLATFORM_DRIVER vt8500_ehci_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_MSM
#include "ehci-msm.c"
#define PLATFORM_DRIVER ehci_msm_driver
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
index 11695d5..ff4e3ae 100644
--- a/drivers/usb/host/ehci-vt8500.c
+++ b/drivers/usb/host/ehci-vt8500.c
@@ -16,52 +16,25 @@
*
*/

+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/platform_device.h>

-static const struct hc_driver vt8500_ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "VT8500 EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
+#include "ehci.h"

- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
+#define DRIVER_DESC "vt8500 On-Chip EHCI Host driver"

- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
+static const char hcd_name[] = "ehci-vt8500";

- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
+static struct hc_driver __read_mostly vt8500_ehci_hc_driver;

- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+static const struct ehci_driver_overrides ehci_vt8500_overrides __initdata = {
+ .reset = ehci_setup,
};

static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32);
@@ -140,11 +113,31 @@ static struct platform_driver vt8500_ehci_driver = {
.remove = vt8500_ehci_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
- .name = "vt8500-ehci",
+ .name = hcd_name,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(vt8500_ehci_ids),
}
};

+static int __init ehci_vt8500_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&vt8500_ehci_hc_driver, &ehci_vt8500_overrides);
+ return platform_driver_register(&vt8500_ehci_driver);
+}
+module_init(ehci_vt8500_init);
+
+static void __exit ehci_vt8500_cleanup(void)
+{
+ platform_driver_unregister(&vt8500_ehci_driver);
+}
+module_exit(ehci_vt8500_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Alexey Charkov");
+MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:vt8500-ehci");
MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
--
1.7.9.5
Tony Prisk
2013-02-07 18:54:18 UTC
Permalink
Post by m***@linaro.org
Separate the vt8500 host controller driver from ehci-hcd host code
into its own driver module.
---
drivers/usb/host/Kconfig | 8 +++++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 5 ---
drivers/usb/host/ehci-vt8500.c | 73 ++++++++++++++++++----------------------
4 files changed, 42 insertions(+), 45 deletions(-)
...
Post by m***@linaro.org
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
index 11695d5..ff4e3ae 100644
--- a/drivers/usb/host/ehci-vt8500.c
+++ b/drivers/usb/host/ehci-vt8500.c
@@ -16,52 +16,25 @@
...
Post by m***@linaro.org
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Alexey Charkov");
+MODULE_LICENSE("GPL");
Should be "GPL v2" as per the license header.
Post by m***@linaro.org
MODULE_ALIAS("platform:vt8500-ehci");
MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
Regards
Tony Prisk
m***@linaro.org
2013-02-07 17:34:06 UTC
Permalink
From: Manjunath Goudar <***@linaro.org>

Separate the Qualcomm On-Chip host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <***@linaro.org>
Cc: Greg KH <***@kroah.com>
Cc: Alan Stern <***@rowland.harvard.edu>
Cc: David Brown <***@codeaurora.org>
Cc: Daniel Walker <***@fifo99.com>
Cc: Bryan Huntsman <***@codeaurora.org>
Cc: Brian Swetland <***@google.com>
Cc: linux-***@vger.kernel.org
Cc: linux-***@vger.kernel.org
---
drivers/usb/host/Kconfig | 5 +--
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 7 ++--
drivers/usb/host/ehci-msm.c | 84 +++++++++++++++++++------------------------
4 files changed, 43 insertions(+), 54 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d20d22c..8d18a6c 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -184,6 +184,7 @@ config USB_EHCI_HCD_ORION
---help---
Enables support for the on-chip EHCI controller on
Morvell Orion chips.
+
config USB_EHCI_HCD_AT91
tristate "Support for Atmel on-chip EHCI USB controller"
depends on USB_EHCI_HCD && ARCH_AT91
@@ -193,7 +194,7 @@ config USB_EHCI_HCD_AT91
Atmel chips.

config USB_EHCI_MSM
- bool "Support for MSM on-chip EHCI USB controller"
+ tristate "Support for MSM on-chip EHCI USB controller"
depends on USB_EHCI_HCD && ARCH_MSM
select USB_EHCI_ROOT_HUB_TT
select USB_MSM_OTG
@@ -209,7 +210,7 @@ config USB_EHCI_TEGRA
boolean "NVIDIA Tegra HCD support"
depends on USB_EHCI_HCD && ARCH_TEGRA
select USB_EHCI_ROOT_HUB_TT
- help
+ --- help---
This driver enables support for the internal USB Host Controllers
found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.

diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index cf71e5d..6c1d0e0 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
obj-$(CONFIG_USB_EHCI_MV) += ehci-mv.o
obj-$(CONFIG_USB_EHCI_HCD_VT8500)+= ehci-vt8500.o
+obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 952f85e..d44115b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1277,11 +1277,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_octeon_driver
#endif

-#ifdef CONFIG_USB_EHCI_MSM
-#include "ehci-msm.c"
-#define PLATFORM_DRIVER ehci_msm_driver
-#endif
-
#ifdef CONFIG_TILE_USB
#include "ehci-tilegx.c"
#define PLATFORM_DRIVER ehci_hcd_tilegx_driver
@@ -1317,6 +1312,8 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_ARCH_AT91) && \
!IS_ENABLED(CONFIG_USB_EHCI_S5P) && \
!IS_ENABLED(CONFIG_USB_EHCI_MV) && \
+ !IS_ENABLED(CONFIG_ARCH_VT8500) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 88a49c8..fdf66a9 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -30,8 +30,19 @@
#include <linux/usb/otg.h>
#include <linux/usb/msm_hsusb_hw.h>

+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include "ehci.h"
+
#define MSM_USB_BASE (hcd->regs)

+#define DRIVER_DESC "Qualcomm On-Chip EHCI Host Controller"
+
+static const char hcd_name[] = "msm_hsusb_host";
+static struct hc_driver __read_mostly msm_hc_driver;
static struct usb_phy *phy;

static int ehci_msm_reset(struct usb_hcd *hcd)
@@ -56,52 +67,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
return 0;
}

-static struct hc_driver msm_hc_driver = {
- .description = hcd_name,
- .product_desc = "Qualcomm On-Chip EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_USB2 | HCD_MEMORY,
-
- .reset = ehci_msm_reset,
- .start = ehci_run,
-
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- /*
- * PM support
- */
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-};
-
static int ehci_msm_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -222,7 +187,32 @@ static struct platform_driver ehci_msm_driver = {
.probe = ehci_msm_probe,
.remove = ehci_msm_remove,
.driver = {
- .name = "msm_hsusb_host",
+ .name = hcd_name,
.pm = &ehci_msm_dev_pm_ops,
},
};
+
+static const struct ehci_driver_overrides msm_overrides __initdata = {
+ .reset = ehci_msm_reset,
+};
+
+static int __init ehci_msm_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&msm_hc_driver, &msm_overrides);
+ return platform_driver_register(&ehci_msm_driver);
+}
+module_init(ehci_msm_init);
+
+static void __exit ehci_msm_cleanup(void)
+{
+ platform_driver_unregister(&ehci_msm_driver);
+}
+module_exit(ehci_msm_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:omap-msm");
+MODULE_LICENSE("GPL");
--
1.7.9.5
Stephen Warren
2013-02-07 18:48:52 UTC
Permalink
Post by m***@linaro.org
Separate the Qualcomm On-Chip host controller driver from ehci-hcd host code
into its own driver module.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
@@ -209,7 +210,7 @@ config USB_EHCI_TEGRA
boolean "NVIDIA Tegra HCD support"
depends on USB_EHCI_HCD && ARCH_TEGRA
select USB_EHCI_ROOT_HUB_TT
- help
+ --- help---
This driver enables support for the internal USB Host Controllers
found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
That seems like an unrelated change. The indentation and space after
first "---" looks wrong too. It looks pretty random which of "help" and
"---help---" is used in this file; if you're going to fix that, I think
fix them all, but in a separate patch.
David Brown
2013-02-07 19:05:01 UTC
Permalink
Post by manjunath.goudar-QSEj5FYQhm4dnm+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:omap-msm");
+MODULE_LICENSE("GPL");
omap-msm? I think you mean msm-ehci.

I don't have any hardware to test this on, so hopefully someone can
chime in after testing it.

David
--
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
Srinivas KANDAGATLA
2013-06-10 09:17:08 UTC
Permalink
From: Srinivas Kandagatla <***@st.com>

Here is new patch-set incorporating all the review comments.

This patch-set adds basic support for STMicroelectronics STixxxx SOCs
which includes STiH415 and STiH416 with B2000 and B2020 board support.

STiH415 and STiH416 are dual-core ARM Cortex-A9 CPU, designed for use in
Set-top-boxes. The SOC support is available in mach-stixxxx which contains
support code for STiH415, STiH416 SOCs including the generic board support.

Only device drivers included in this patch set are UART and pinctrl, other
drivers will be added in future.

The reason for adding two SOCs at this patch set is to show that no new
C code is required for second SOC(STiH416) support.

Thankyou all for reviewing the first set of RFC patches.
I would appreciate any feedback on these patches.

Changes since RFC:
- st-asc Serial driver:
- modified kconfig to remove default y
- removed all the forward declaration.
- use dynamic major numbering.
- merge header-file in to driver.

- ARM Global timer:
- moved to drivers/clocksource.
- added revision check in driver.
- removed unused header file.
- moved to u64 from union gt_counter
- comments added in get_counter
- removed leftover debug code.
- moved code to use __raw_readl/writel.
- used DIV_ROUND_CLOSEST
- added check in interrupt handler.
- expanded CE and CS acronyms usage.
- Fixed minimum clock ticks value.
- move to use clocksource_register_hz
- added arch sched_clock support.
- added ERRATA 740657 workaround.

- ST-System Configuration Registers:
- moved from syscon usage to st specific driver.

- ST Pinctrl support:
- fixed few typos in the documentation.
- moved some of the retime offset information to driver.

- STixxxx Support:
- all the SOC support code is moved to mach-stixxxx
- seperated DEBUG_LL code to new patch.
- removed unnecessary #interrupt-cells
- renamed uart to serial
- moved to multi_v7_defconfig
- used menuconfig in mach-stixxx/Kconfig
- removed of_platform_populate as generic code does it for you.
- scu address is ioremaped.

Thanks,
srini

Srinivas Kandagatla (10):
serial:st-asc: Add ST ASC driver.
regmap: Add regmap_field APIs
mfd:stixxxx-syscfg: Add ST System Configuration support.
pinctrl:stixxxx: Add pinctrl and pinconf support.
ARM:stixxxx: Add STiH415 SOC support
ARM:stixxxx: Add STiH416 SOC support
ARM:stixxxx: Add DEBUG_LL console support
ARM:stixxxx: Add stixxxx options to multi_v7_defconfig
ARM:stih41x: Add B2000 board support
ARM:stih41x: Add B2020 board support

Stuart Menefy (1):
clocksource:global_timer: Add ARM global timer support.

Documentation/arm/stixxxx/overview.txt | 33 +
Documentation/arm/stixxxx/stih415-overview.txt | 12 +
Documentation/arm/stixxxx/stih416-overview.txt | 12 +
.../devicetree/bindings/arm/global_timer.txt | 21 +
.../devicetree/bindings/mfd/stixxxx-syscfg.txt | 18 +
.../bindings/pinctrl/pinctrl-stixxxx.txt | 116 ++
.../devicetree/bindings/tty/serial/st-asc.txt | 18 +
MAINTAINERS | 11 +
arch/arm/Kconfig | 2 +
arch/arm/Kconfig.debug | 38 +
arch/arm/Makefile | 1 +
arch/arm/boot/dts/Makefile | 4 +
arch/arm/boot/dts/stih415-b2000.dts | 15 +
arch/arm/boot/dts/stih415-b2020.dts | 15 +
arch/arm/boot/dts/stih415-clock.dtsi | 38 +
arch/arm/boot/dts/stih415-pinctrl.dtsi | 326 ++++++
arch/arm/boot/dts/stih415.dtsi | 102 ++
arch/arm/boot/dts/stih416-b2000.dts | 16 +
arch/arm/boot/dts/stih416-b2020.dts | 16 +
arch/arm/boot/dts/stih416-clock.dtsi | 41 +
arch/arm/boot/dts/stih416-pinctrl.dtsi | 377 ++++++
arch/arm/boot/dts/stih416.dtsi | 111 ++
arch/arm/boot/dts/stih41x-b2000.dtsi | 41 +
arch/arm/boot/dts/stih41x-b2020.dtsi | 42 +
arch/arm/boot/dts/stih41x.dtsi | 38 +
arch/arm/boot/dts/stixxxx-pincfg.h | 94 ++
arch/arm/configs/multi_v7_defconfig | 32 +-
arch/arm/include/debug/stixxxx.S | 61 +
arch/arm/mach-stixxxx/Kconfig | 45 +
arch/arm/mach-stixxxx/Makefile | 2 +
arch/arm/mach-stixxxx/board-dt.c | 50 +
arch/arm/mach-stixxxx/headsmp.S | 44 +
arch/arm/mach-stixxxx/platsmp.c | 117 ++
arch/arm/mach-stixxxx/smp.h | 19 +
drivers/base/regmap/internal.h | 8 +
drivers/base/regmap/regmap.c | 104 ++
drivers/clocksource/Kconfig | 13 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/arm_global_timer.c | 368 ++++++
drivers/mfd/Kconfig | 10 +
drivers/mfd/Makefile | 1 +
drivers/mfd/stixxxx-syscfg.c | 168 +++
drivers/pinctrl/Kconfig | 11 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-stixxxx.c | 1212 ++++++++++++++++++++
drivers/pinctrl/pinctrl-stixxxx.h | 197 ++++
drivers/tty/serial/Kconfig | 16 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/st-asc.c | 911 +++++++++++++++
include/linux/mfd/stixxxx-syscfg.h | 15 +
include/linux/regmap.h | 42 +
include/uapi/linux/serial_core.h | 3 +
52 files changed, 4993 insertions(+), 17 deletions(-)
create mode 100644 Documentation/arm/stixxxx/overview.txt
create mode 100644 Documentation/arm/stixxxx/stih415-overview.txt
create mode 100644 Documentation/arm/stixxxx/stih416-overview.txt
create mode 100644 Documentation/devicetree/bindings/arm/global_timer.txt
create mode 100644 Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
create mode 100644 Documentation/devicetree/bindings/tty/serial/st-asc.txt
create mode 100644 arch/arm/boot/dts/stih415-b2000.dts
create mode 100644 arch/arm/boot/dts/stih415-b2020.dts
create mode 100644 arch/arm/boot/dts/stih415-clock.dtsi
create mode 100644 arch/arm/boot/dts/stih415-pinctrl.dtsi
create mode 100644 arch/arm/boot/dts/stih415.dtsi
create mode 100644 arch/arm/boot/dts/stih416-b2000.dts
create mode 100644 arch/arm/boot/dts/stih416-b2020.dts
create mode 100644 arch/arm/boot/dts/stih416-clock.dtsi
create mode 100644 arch/arm/boot/dts/stih416-pinctrl.dtsi
create mode 100644 arch/arm/boot/dts/stih416.dtsi
create mode 100644 arch/arm/boot/dts/stih41x-b2000.dtsi
create mode 100644 arch/arm/boot/dts/stih41x-b2020.dtsi
create mode 100644 arch/arm/boot/dts/stih41x.dtsi
create mode 100644 arch/arm/boot/dts/stixxxx-pincfg.h
create mode 100644 arch/arm/include/debug/stixxxx.S
create mode 100644 arch/arm/mach-stixxxx/Kconfig
create mode 100644 arch/arm/mach-stixxxx/Makefile
create mode 100644 arch/arm/mach-stixxxx/board-dt.c
create mode 100644 arch/arm/mach-stixxxx/headsmp.S
create mode 100644 arch/arm/mach-stixxxx/platsmp.c
create mode 100644 arch/arm/mach-stixxxx/smp.h
create mode 100644 drivers/clocksource/arm_global_timer.c
create mode 100644 drivers/mfd/stixxxx-syscfg.c
create mode 100644 drivers/pinctrl/pinctrl-stixxxx.c
create mode 100644 drivers/pinctrl/pinctrl-stixxxx.h
create mode 100644 drivers/tty/serial/st-asc.c
create mode 100644 include/linux/mfd/stixxxx-syscfg.h
--
1.7.6.5
Srinivas KANDAGATLA
2013-06-10 09:21:00 UTC
Permalink
This patch adds support to ASC (asynchronous serial controller)
driver, which is basically a standard serial driver. This IP is common
across all the ST parts for settop box platforms.

ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
It support all industry standard baud rates.

Signed-off-by: Srinivas Kandagatla <***@st.com>
CC: Stephen Gallimore <***@st.com>
CC: Stuart Menefy <***@st.com>
CC: Arnd Bergmann <***@arndb.de>
CC: Greg Kroah-Hartman <***@linuxfoundation.org>
---
.../devicetree/bindings/tty/serial/st-asc.txt | 18 +
drivers/tty/serial/Kconfig | 16 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/st-asc.c | 911 ++++++++++++++++++++
include/uapi/linux/serial_core.h | 3 +
5 files changed, 949 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/tty/serial/st-asc.txt
create mode 100644 drivers/tty/serial/st-asc.c

diff --git a/Documentation/devicetree/bindings/tty/serial/st-asc.txt b/Documentation/devicetree/bindings/tty/serial/st-asc.txt
new file mode 100644
index 0000000..75d877f
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/st-asc.txt
@@ -0,0 +1,18 @@
+*st-asc(Serial Port)
+
+Required properties:
+- compatible : Should be "st,asc".
+- reg, reg-names, interrupts, interrupt-names : Standard way to define device
+ resources with names. look in
+ Documentation/devicetree/bindings/resource-names.txt
+
+Optional properties:
+- st,hw-flow-ctrl bool flag to enable hardware flow control.
+- st,force-m1 bool flat to force asc to be in Mode-1 recommeded
+ for high bit rates (above 19.2K)
+Example:
+***@fe440000{
+ compatible = "st,asc";
+ reg = <0xfe440000 0x2c>;
+ interrupts = <0 209 0>;
+};
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 7e7006f..0c6ddf6 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1484,6 +1484,22 @@ config SERIAL_RP2_NR_UARTS
If multiple cards are present, the default limit of 32 ports may
need to be increased.

+config SERIAL_ST_ASC
+ tristate "ST ASC serial port support"
+ select SERIAL_CORE
+ help
+ This driver is for the on-chip Asychronous Serial Controller on
+ STMicroelectronics STixxxx SoCs.
+ ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
+ It support all industry standard baud rates.
+
+ If unsure, say N.
+
+config SERIAL_ST_ASC_CONSOLE
+ bool "Support for console on ST ASC"
+ depends on SERIAL_ST_ASC=y
+ select SERIAL_CORE_CONSOLE
+
endmenu

endif # TTY
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index eedfec4..536ccc7 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
+obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
new file mode 100644
index 0000000..6592c04
--- /dev/null
+++ b/drivers/tty/serial/st-asc.c
@@ -0,0 +1,911 @@
+/*
+ * st-asc.c: ST Asynchronous serial controller (ASC) driver
+ *
+ * Copyright (C) 2003-2013 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#if defined(CONFIG_SERIAL_ST_ASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/serial_core.h>
+#include <linux/clk.h>
+
+#define DRIVER_NAME "st-asc"
+#define ASC_SERIAL_NAME "ttyAS"
+#define ASC_FIFO_SIZE 16
+#define ASC_MAX_PORTS 8
+
+struct asc_port {
+ struct uart_port port;
+ struct clk *clk;
+ unsigned int hw_flow_control:1;
+ unsigned int check_parity:1;
+ unsigned int force_m1:1;
+};
+
+static struct asc_port asc_ports[ASC_MAX_PORTS];
+static struct uart_driver asc_uart_driver;
+
+/*---- UART Register definitions ------------------------------*/
+
+/* Register offsets */
+
+#define ASC_BAUDRATE 0x00
+#define ASC_TXBUF 0x04
+#define ASC_RXBUF 0x08
+#define ASC_CTL 0x0C
+#define ASC_INTEN 0x10
+#define ASC_STA 0x14
+#define ASC_GUARDTIME 0x18
+#define ASC_TIMEOUT 0x1C
+#define ASC_TXRESET 0x20
+#define ASC_RXRESET 0x24
+#define ASC_RETRIES 0x28
+
+/* ASC_RXBUF */
+#define ASC_RXBUF_PE 0x100
+#define ASC_RXBUF_FE 0x200
+
+/* ASC_CTL */
+
+#define ASC_CTL_MODE_MSK 0x0007
+#define ASC_CTL_MODE_8BIT 0x0001
+#define ASC_CTL_MODE_7BIT_PAR 0x0003
+#define ASC_CTL_MODE_9BIT 0x0004
+#define ASC_CTL_MODE_8BIT_WKUP 0x0005
+#define ASC_CTL_MODE_8BIT_PAR 0x0007
+#define ASC_CTL_STOP_MSK 0x0018
+#define ASC_CTL_STOP_HALFBIT 0x0000
+#define ASC_CTL_STOP_1BIT 0x0008
+#define ASC_CTL_STOP_1_HALFBIT 0x0010
+#define ASC_CTL_STOP_2BIT 0x0018
+#define ASC_CTL_PARITYODD 0x0020
+#define ASC_CTL_LOOPBACK 0x0040
+#define ASC_CTL_RUN 0x0080
+#define ASC_CTL_RXENABLE 0x0100
+#define ASC_CTL_SCENABLE 0x0200
+#define ASC_CTL_FIFOENABLE 0x0400
+#define ASC_CTL_CTSENABLE 0x0800
+#define ASC_CTL_BAUDMODE 0x1000
+
+/* ASC_GUARDTIME */
+
+#define ASC_GUARDTIME_MSK 0x00FF
+
+/* ASC_INTEN */
+
+#define ASC_INTEN_RBE 0x0001
+#define ASC_INTEN_TE 0x0002
+#define ASC_INTEN_THE 0x0004
+#define ASC_INTEN_PE 0x0008
+#define ASC_INTEN_FE 0x0010
+#define ASC_INTEN_OE 0x0020
+#define ASC_INTEN_TNE 0x0040
+#define ASC_INTEN_TOI 0x0080
+#define ASC_INTEN_RHF 0x0100
+
+/* ASC_RETRIES */
+
+#define ASC_RETRIES_MSK 0x00FF
+
+/* ASC_RXBUF */
+
+#define ASC_RXBUF_MSK 0x03FF
+
+/* ASC_STA */
+
+#define ASC_STA_RBF 0x0001
+#define ASC_STA_TE 0x0002
+#define ASC_STA_THE 0x0004
+#define ASC_STA_PE 0x0008
+#define ASC_STA_FE 0x0010
+#define ASC_STA_OE 0x0020
+#define ASC_STA_TNE 0x0040
+#define ASC_STA_TOI 0x0080
+#define ASC_STA_RHF 0x0100
+#define ASC_STA_TF 0x0200
+#define ASC_STA_NKD 0x0400
+
+/* ASC_TIMEOUT */
+
+#define ASC_TIMEOUT_MSK 0x00FF
+
+/* ASC_TXBUF */
+
+#define ASC_TXBUF_MSK 0x01FF
+
+/*---- Inline function definitions ---------------------------*/
+
+static inline struct asc_port *to_asc_port(struct uart_port *port)
+{
+ return container_of(port, struct asc_port, port);
+}
+
+static inline u32 asc_in(struct uart_port *port, u32 offset)
+{
+ return readl(port->membase + offset);
+}
+
+static inline void asc_out(struct uart_port *port, u32 offset, u32 value)
+{
+ writel(value, port->membase + offset);
+}
+
+/*
+ * Some simple utility functions to enable and disable interrupts.
+ * Note that these need to be called with interrupts disabled.
+ */
+static inline void asc_disable_tx_interrupts(struct uart_port *port)
+{
+ u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_THE;
+ asc_out(port, ASC_INTEN, intenable);
+ (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
+}
+
+static inline void asc_enable_tx_interrupts(struct uart_port *port)
+{
+ u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_THE;
+ asc_out(port, ASC_INTEN, intenable);
+}
+
+static inline void asc_disable_rx_interrupts(struct uart_port *port)
+{
+ u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_RBE;
+ asc_out(port, ASC_INTEN, intenable);
+ (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
+}
+
+static inline void asc_enable_rx_interrupts(struct uart_port *port)
+{
+ u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_RBE;
+ asc_out(port, ASC_INTEN, intenable);
+}
+
+static inline u32 asc_txfifo_is_empty(struct uart_port *port)
+{
+ return asc_in(port, ASC_STA) & ASC_STA_TE;
+}
+
+static inline int asc_txfifo_is_full(struct uart_port *port)
+{
+ return asc_in(port, ASC_STA) & ASC_STA_TF;
+}
+
+static inline const char *asc_port_name(struct uart_port *port)
+{
+ return to_platform_device(port->dev)->name;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * This section contains code to support the use of the ASC as a
+ * generic serial port.
+ */
+
+static inline unsigned asc_hw_txroom(struct uart_port *port)
+{
+ u32 status = asc_in(port, ASC_STA);
+
+ if (status & ASC_STA_THE)
+ return port->fifosize / 2;
+ else if (!(status & ASC_STA_TF))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Start transmitting chars.
+ * This is called from both interrupt and task level.
+ * Either way interrupts are disabled.
+ */
+static void asc_transmit_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+ int txroom;
+ unsigned char c;
+
+ txroom = asc_hw_txroom(port);
+
+ if ((txroom != 0) && port->x_char) {
+ c = port->x_char;
+ port->x_char = 0;
+ asc_out(port, ASC_TXBUF, c);
+ port->icount.tx++;
+ txroom = asc_hw_txroom(port);
+ }
+
+ if (uart_tx_stopped(port)) {
+ /*
+ * We should try and stop the hardware here, but I
+ * don't think the ASC has any way to do that.
+ */
+ asc_disable_tx_interrupts(port);
+ return;
+ }
+
+ if (uart_circ_empty(xmit)) {
+ asc_disable_tx_interrupts(port);
+ return;
+ }
+
+ if (txroom == 0)
+ return;
+
+ do {
+ c = xmit->buf[xmit->tail];
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ asc_out(port, ASC_TXBUF, c);
+ port->icount.tx++;
+ txroom--;
+ } while ((txroom > 0) && (!uart_circ_empty(xmit)));
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ asc_disable_tx_interrupts(port);
+}
+
+static void asc_receive_chars(struct uart_port *port)
+{
+ int count;
+ struct asc_port *ascport = to_asc_port(port);
+ struct tty_port *tport = &port->state->port;
+ int copied = 0;
+ unsigned long status;
+ unsigned long c = 0;
+ char flag;
+ int overrun;
+
+ if (port->irq_wake)
+ pm_wakeup_event(tport->tty->dev, 0);
+
+ while (1) {
+ status = asc_in(port, ASC_STA);
+ if (status & ASC_STA_RHF)
+ count = port->fifosize / 2;
+ else if (status & ASC_STA_RBF)
+ count = 1;
+ else
+ break;
+
+ /*
+ * Check for overrun before reading any data from the
+ * RX FIFO, as this clears the overflow error condition.
+ */
+ overrun = status & ASC_STA_OE;
+
+ for (; count != 0; count--) {
+ c = asc_in(port, ASC_RXBUF);
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (unlikely(c & ASC_RXBUF_FE)) {
+ if (c == ASC_RXBUF_FE) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ flag = TTY_BREAK;
+ } else {
+ port->icount.frame++;
+ flag = TTY_FRAME;
+ }
+ } else if (ascport->check_parity &&
+ unlikely(c & ASC_RXBUF_PE)) {
+ port->icount.parity++;
+ flag = TTY_PARITY;
+ }
+
+ if (uart_handle_sysrq_char(port, c))
+ continue;
+ tty_insert_flip_char(tport, c & 0xff, flag);
+ }
+ if (overrun) {
+ port->icount.overrun++;
+ tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+ }
+
+ copied = 1;
+ }
+
+ if (copied) {
+ /* Tell the rest of the system the news. New characters! */
+ tty_flip_buffer_push(tport);
+ }
+}
+
+static irqreturn_t asc_interrupt(int irq, void *ptr)
+{
+ struct uart_port *port = ptr;
+ u32 status;
+
+ spin_lock(&port->lock);
+
+ status = asc_in(port, ASC_STA);
+
+ if (status & ASC_STA_RBF) {
+ /* Receive FIFO not empty */
+ asc_receive_chars(port);
+ }
+
+ if ((status & ASC_STA_THE) &&
+ (asc_in(port, ASC_INTEN) & ASC_INTEN_THE)) {
+ /* Transmitter FIFO at least half empty */
+ asc_transmit_chars(port);
+ }
+
+ spin_unlock(&port->lock);
+
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * UART Functions
+ */
+
+static unsigned int asc_tx_empty(struct uart_port *port)
+{
+ return asc_txfifo_is_empty(port) ? TIOCSER_TEMT : 0;
+}
+
+static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /*
+ * This routine is used for seting signals of: DTR, DCD, CTS/RTS
+ * We use ASC's hardware for CTS/RTS, so don't need any for that.
+ * Some boards have DTR and DCD implemented using PIO pins,
+ * code to do this should be hooked in here.
+ */
+}
+
+static unsigned int asc_get_mctrl(struct uart_port *port)
+{
+ /*
+ * This routine is used for geting signals of: DTR, DCD, DSR, RI,
+ * and CTS/RTS
+ */
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* There are probably characters waiting to be transmitted. */
+static void asc_start_tx(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+
+ if (!uart_circ_empty(xmit))
+ asc_enable_tx_interrupts(port);
+}
+
+/* Transmit stop */
+static void asc_stop_tx(struct uart_port *port)
+{
+ asc_disable_tx_interrupts(port);
+}
+
+/* Receive stop */
+static void asc_stop_rx(struct uart_port *port)
+{
+ asc_disable_rx_interrupts(port);
+}
+
+/* Force modem status interrupts on */
+static void asc_enable_ms(struct uart_port *port)
+{
+ /* Nothing here yet .. */
+}
+
+/* Handle breaks - ignored by us */
+static void asc_break_ctl(struct uart_port *port, int break_state)
+{
+ /* Nothing here yet .. */
+}
+
+/*
+ * Enable port for reception.
+ */
+static int asc_startup(struct uart_port *port)
+{
+ if (request_irq(port->irq, asc_interrupt, IRQF_NO_SUSPEND,
+ asc_port_name(port), port)) {
+ dev_err(port->dev, "cannot allocate irq.\n");
+ return -ENODEV;
+ }
+
+ asc_transmit_chars(port);
+ asc_enable_rx_interrupts(port);
+
+ return 0;
+}
+
+static void asc_shutdown(struct uart_port *port)
+{
+ asc_disable_tx_interrupts(port);
+ asc_disable_rx_interrupts(port);
+ free_irq(port->irq, port);
+}
+
+static void asc_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct asc_port *ascport = to_asc_port(port);
+ unsigned long flags = 0;
+ u32 ctl;
+
+ switch (state) {
+ case UART_PM_STATE_ON:
+ clk_prepare_enable(ascport->clk);
+ break;
+ case UART_PM_STATE_OFF:
+ /*
+ * Disable the ASC baud rate generator, which is as close as
+ * we can come to turning it off. Note this is not called with
+ * the port spinlock held.
+ */
+ spin_lock_irqsave(&port->lock, flags);
+ ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN;
+ asc_out(port, ASC_CTL, ctl);
+ spin_unlock_irqrestore(&port->lock, flags);
+ clk_disable_unprepare(ascport->clk);
+ break;
+ }
+}
+
+static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct asc_port *ascport = to_asc_port(port);
+ unsigned int baud;
+ u32 ctrl_val;
+ tcflag_t cflag;
+ unsigned long flags;
+
+ port->uartclk = clk_get_rate(ascport->clk);
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ cflag = termios->c_cflag;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* read control register */
+ ctrl_val = asc_in(port, ASC_CTL);
+
+ /* stop serial port and reset value */
+ asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
+ ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
+
+ /* reset fifo rx & tx */
+ asc_out(port, ASC_TXRESET, 1);
+ asc_out(port, ASC_RXRESET, 1);
+
+ /* set character length */
+ if ((cflag & CSIZE) == CS7) {
+ ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
+ } else {
+ ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR :
+ ASC_CTL_MODE_8BIT;
+ }
+
+ ascport->check_parity = (cflag & PARENB) ? 1 : 0;
+
+ /* set stop bit */
+ ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
+
+ /* odd parity */
+ if (cflag & PARODD)
+ ctrl_val |= ASC_CTL_PARITYODD;
+
+ /* hardware flow control */
+ if ((cflag & CRTSCTS) && ascport->hw_flow_control)
+ ctrl_val |= ASC_CTL_CTSENABLE;
+
+ if ((baud < 19200) && !ascport->force_m1) {
+ asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud)));
+ } else {
+ /*
+ * MODE 1: recommended for high bit rates (above 19.2K)
+ *
+ * baudrate * 16 * 2^16
+ * ASCBaudRate = ------------------------
+ * inputclock
+ *
+ * However to keep the maths inside 32bits we divide top and
+ * bottom by 64. The +1 is to avoid a divide by zero if the
+ * input clock rate is something unexpected.
+ */
+ u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1);
+ asc_out(port, ASC_BAUDRATE, counter);
+ ctrl_val |= ASC_CTL_BAUDMODE;
+ }
+
+ uart_update_timeout(port, cflag, baud);
+
+ /* Set the timeout */
+ asc_out(port, ASC_TIMEOUT, 20);
+
+ /* write final value and enable port */
+ asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN));
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *asc_type(struct uart_port *port)
+{
+ return (port->type == PORT_ASC) ? DRIVER_NAME : NULL;
+}
+
+static void asc_release_port(struct uart_port *port)
+{
+}
+
+static int asc_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+/*
+ * Called when the port is opened, and UPF_BOOT_AUTOCONF flag is set
+ * Set type field if successful
+ */
+static void asc_config_port(struct uart_port *port, int flags)
+{
+ if ((flags & UART_CONFIG_TYPE))
+ port->type = PORT_ASC;
+}
+
+static int
+asc_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ /* No user changeable parameters */
+ return -EINVAL;
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context (i.e. kgdb).
+ */
+
+static int asc_get_poll_char(struct uart_port *port)
+{
+ if (!(asc_in(port, ASC_STA) & ASC_STA_RBF))
+ return NO_POLL_CHAR;
+
+ return asc_in(port, ASC_RXBUF);
+}
+
+static void asc_put_poll_char(struct uart_port *port, unsigned char c)
+{
+ while (asc_txfifo_is_full(port))
+ cpu_relax();
+ asc_out(port, ASC_TXBUF, c);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+/*---------------------------------------------------------------------*/
+
+static struct uart_ops asc_uart_ops = {
+ .tx_empty = asc_tx_empty,
+ .set_mctrl = asc_set_mctrl,
+ .get_mctrl = asc_get_mctrl,
+ .start_tx = asc_start_tx,
+ .stop_tx = asc_stop_tx,
+ .stop_rx = asc_stop_rx,
+ .enable_ms = asc_enable_ms,
+ .break_ctl = asc_break_ctl,
+ .startup = asc_startup,
+ .shutdown = asc_shutdown,
+ .set_termios = asc_set_termios,
+ .type = asc_type,
+ .release_port = asc_release_port,
+ .request_port = asc_request_port,
+ .config_port = asc_config_port,
+ .verify_port = asc_verify_port,
+ .pm = asc_pm,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = asc_get_poll_char,
+ .poll_put_char = asc_put_poll_char,
+#endif /* CONFIG_CONSOLE_POLL */
+};
+
+static int asc_init_port(struct asc_port *ascport,
+ struct platform_device *pdev)
+{
+ struct uart_port *port = &ascport->port;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get io resource\n");
+ return -ENODEV;
+ }
+
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->ops = &asc_uart_ops;
+ port->fifosize = ASC_FIFO_SIZE;
+ port->dev = &pdev->dev;
+ port->mapbase = res->start;
+ port->irq = platform_get_irq(pdev, 0);
+
+ port->membase = devm_request_and_ioremap(&pdev->dev, res);
+ if (!port->membase) {
+ dev_err(&pdev->dev, "Unable to request io memory\n");
+ return -ENODEV;
+ }
+
+ spin_lock_init(&port->lock);
+
+ ascport->clk = devm_clk_get(&pdev->dev, NULL);
+
+ if (WARN_ON(IS_ERR(ascport->clk)))
+ return -EINVAL;
+ /* ensure that clk rate is correct by enabling the clk */
+ clk_prepare_enable(ascport->clk);
+ ascport->port.uartclk = clk_get_rate(ascport->clk);
+ WARN_ON(ascport->port.uartclk == 0);
+ clk_disable_unprepare(ascport->clk);
+
+ return 0;
+}
+
+static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int id;
+
+ if (!np)
+ return NULL;
+
+ id = of_alias_get_id(np, ASC_SERIAL_NAME);
+ if (WARN_ON(id >= ASC_MAX_PORTS))
+ return NULL;
+
+ asc_ports[id].hw_flow_control = of_property_read_bool(np,
+ "st,hw-flow-control");
+ asc_ports[id].force_m1 = of_property_read_bool(np, "st,force_m1");
+ asc_ports[id].port.line = id;
+ return &asc_ports[id];
+}
+
+static struct of_device_id asc_match[] = {
+ { .compatible = "st,asc", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, asc_match);
+
+static int asc_serial_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct asc_port *ascport;
+
+ ascport = asc_of_get_asc_port(pdev);
+ if (!ascport)
+ return -ENODEV;
+
+ ret = asc_init_port(ascport, pdev);
+ if (ret)
+ return ret;
+
+ ret = uart_add_one_port(&asc_uart_driver, &ascport->port);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, &ascport->port);
+
+ return 0;
+}
+
+static int asc_serial_remove(struct platform_device *pdev)
+{
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ return uart_remove_one_port(&asc_uart_driver, port);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int asc_serial_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ return uart_suspend_port(&asc_uart_driver, port);
+}
+
+static int asc_serial_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ if (pdev->dev.pins->default_state) {
+ if (pinctrl_select_state(pdev->dev.pins->p,
+ pdev->dev.pins->default_state) < 0)
+ return -EBUSY;
+ }
+
+ return uart_resume_port(&asc_uart_driver, port);
+}
+
+#endif /* CONFIG_PM_SLEEP */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE
+static void asc_console_putchar(struct uart_port *port, int ch)
+{
+ unsigned int timeout = 1000000;
+
+ /* Wait for upto 1 second in case flow control is stopping us. */
+ while (--timeout && asc_txfifo_is_full(port))
+ udelay(1);
+
+ asc_out(port, ASC_TXBUF, ch);
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ */
+
+static void asc_console_write(struct console *co, const char *s, unsigned count)
+{
+ struct uart_port *port = &asc_ports[co->index].port;
+ unsigned long flags;
+ unsigned long timeout = 1000000;
+ int locked = 1;
+ u32 intenable;
+
+ local_irq_save(flags);
+ if (port->sysrq)
+ locked = 0; /* asc_interrupt has already claimed the lock */
+ else if (oops_in_progress)
+ locked = spin_trylock(&port->lock);
+ else
+ spin_lock(&port->lock);
+
+ /*
+ * Disable interrupts so we don't get the IRQ line bouncing
+ * up and down while interrupts are disabled.
+ */
+ intenable = asc_in(port, ASC_INTEN);
+ asc_out(port, ASC_INTEN, 0);
+ (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
+
+ uart_console_write(port, s, count, asc_console_putchar);
+
+ while (--timeout && !asc_txfifo_is_empty(port))
+ udelay(1);
+
+ asc_out(port, ASC_INTEN, intenable);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
+}
+
+static int asc_console_setup(struct console *co, char *options)
+{
+ struct asc_port *ascport;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index >= ASC_MAX_PORTS)
+ return -ENODEV;
+
+ ascport = &asc_ports[co->index];
+
+ /*
+ * This driver does not support early console initialization
+ * (use ARM early printk support instead), so we only expect
+ * this to be called during the uart port registration when the
+ * driver gets probed and the port should be mapped at that point.
+ */
+ BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&ascport->port, co, baud, parity, bits, flow);
+}
+
+static struct console asc_console = {
+ .name = ASC_SERIAL_NAME,
+ .device = uart_console_device,
+ .write = asc_console_write,
+ .setup = asc_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &asc_uart_driver,
+};
+
+#define ASC_SERIAL_CONSOLE (&asc_console)
+
+#else
+#define ASC_SERIAL_CONSOLE NULL
+#endif /* CONFIG_SERIAL_ST_ASC_CONSOLE */
+
+static struct uart_driver asc_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = DRIVER_NAME,
+ .dev_name = ASC_SERIAL_NAME,
+ .major = 0,
+ .minor = 0,
+ .nr = ASC_MAX_PORTS,
+ .cons = ASC_SERIAL_CONSOLE,
+};
+
+static const struct dev_pm_ops asc_serial_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume)
+};
+
+static struct platform_driver asc_serial_driver = {
+ .probe = asc_serial_probe,
+ .remove = asc_serial_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .pm = &asc_serial_pm_ops,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(asc_match),
+ },
+};
+
+static int __init asc_init(void)
+{
+ int ret;
+ static char banner[] __initdata =
+ KERN_INFO "STMicroelectronics ASC driver initialized\n";
+
+ printk(banner);
+
+ ret = uart_register_driver(&asc_uart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&asc_serial_driver);
+ if (ret)
+ uart_unregister_driver(&asc_uart_driver);
+
+ return ret;
+}
+
+static void __exit asc_exit(void)
+{
+ platform_driver_unregister(&asc_serial_driver);
+ uart_unregister_driver(&asc_uart_driver);
+}
+
+module_init(asc_init);
+module_exit(asc_exit);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("STMicroelectronics (R&D) Limited");
+MODULE_DESCRIPTION("STMicroelectronics ASC serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 74c2bf7..ec80e01 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -226,4 +226,7 @@
/* Rocketport EXPRESS/INFINITY */
#define PORT_RP2 102

+/* ST ASC type numbers */
+#define PORT_ASC 103
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
1.7.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Russell King - ARM Linux
2013-06-10 09:35:11 UTC
Permalink
Post by Srinivas KANDAGATLA
This patch adds support to ASC (asynchronous serial controller)
driver, which is basically a standard serial driver. This IP is common
across all the ST parts for settop box platforms.
ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
It support all industry standard baud rates.
Your driver is not POSIX compliant.
Post by Srinivas KANDAGATLA
+ for (; count != 0; count--) {
+ c = asc_in(port, ASC_RXBUF);
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (unlikely(c & ASC_RXBUF_FE)) {
+ if (c == ASC_RXBUF_FE) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ flag = TTY_BREAK;
+ } else {
+ port->icount.frame++;
+ flag = TTY_FRAME;
+ }
+ } else if (ascport->check_parity &&
+ unlikely(c & ASC_RXBUF_PE)) {
+ port->icount.parity++;
+ flag = TTY_PARITY;
+ }
+
+ if (uart_handle_sysrq_char(port, c))
+ continue;
+ tty_insert_flip_char(tport, c & 0xff, flag);
+ }
+ if (overrun) {
+ port->icount.overrun++;
+ tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+ }
No support for ignoring error conditions. No support for ignoring all
Post by Srinivas KANDAGATLA
+static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct asc_port *ascport = to_asc_port(port);
+ unsigned int baud;
+ u32 ctrl_val;
+ tcflag_t cflag;
+ unsigned long flags;
+
+ port->uartclk = clk_get_rate(ascport->clk);
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ cflag = termios->c_cflag;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* read control register */
+ ctrl_val = asc_in(port, ASC_CTL);
+
+ /* stop serial port and reset value */
+ asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
+ ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
+
+ /* reset fifo rx & tx */
+ asc_out(port, ASC_TXRESET, 1);
+ asc_out(port, ASC_RXRESET, 1);
+
+ /* set character length */
+ if ((cflag & CSIZE) == CS7) {
+ ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
+ } else {
+ ASC_CTL_MODE_8BIT;
+ }
+
+ ascport->check_parity = (cflag & PARENB) ? 1 : 0;
+
+ /* set stop bit */
+ ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
+
+ /* odd parity */
+ if (cflag & PARODD)
+ ctrl_val |= ASC_CTL_PARITYODD;
+
+ /* hardware flow control */
+ if ((cflag & CRTSCTS) && ascport->hw_flow_control)
+ ctrl_val |= ASC_CTL_CTSENABLE;
This doesn't reflect those facts back into the termios structure to
indicate that they aren't supported.

Consider using uart_port's ignore and read status masks to implement
the break, framing, parity and overrun checking in your interrupt
handler using the same methodology as drivers like 8250, amba-pl011
etc. That will help you get these code sequences correct.
Srinivas KANDAGATLA
2013-06-10 11:53:55 UTC
Permalink
Thankyou for your comment and suggestion,
I will fix the POSIX compliant issue.
Post by Russell King - ARM Linux
Post by Srinivas KANDAGATLA
This patch adds support to ASC (asynchronous serial controller)
driver, which is basically a standard serial driver. This IP is common
across all the ST parts for settop box platforms.
ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
It support all industry standard baud rates.
Your driver is not POSIX compliant.
Post by Srinivas KANDAGATLA
+ for (; count != 0; count--) {
+ c = asc_in(port, ASC_RXBUF);
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (unlikely(c & ASC_RXBUF_FE)) {
+ if (c == ASC_RXBUF_FE) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ flag = TTY_BREAK;
+ } else {
+ port->icount.frame++;
+ flag = TTY_FRAME;
+ }
+ } else if (ascport->check_parity &&
+ unlikely(c & ASC_RXBUF_PE)) {
+ port->icount.parity++;
+ flag = TTY_PARITY;
+ }
+
+ if (uart_handle_sysrq_char(port, c))
+ continue;
+ tty_insert_flip_char(tport, c & 0xff, flag);
+ }
+ if (overrun) {
+ port->icount.overrun++;
+ tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+ }
No support for ignoring error conditions. No support for ignoring all
Post by Srinivas KANDAGATLA
+static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct asc_port *ascport = to_asc_port(port);
+ unsigned int baud;
+ u32 ctrl_val;
+ tcflag_t cflag;
+ unsigned long flags;
+
+ port->uartclk = clk_get_rate(ascport->clk);
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ cflag = termios->c_cflag;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* read control register */
+ ctrl_val = asc_in(port, ASC_CTL);
+
+ /* stop serial port and reset value */
+ asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
+ ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
+
+ /* reset fifo rx & tx */
+ asc_out(port, ASC_TXRESET, 1);
+ asc_out(port, ASC_RXRESET, 1);
+
+ /* set character length */
+ if ((cflag & CSIZE) == CS7) {
+ ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
+ } else {
+ ASC_CTL_MODE_8BIT;
+ }
+
+ ascport->check_parity = (cflag & PARENB) ? 1 : 0;
+
+ /* set stop bit */
+ ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
+
+ /* odd parity */
+ if (cflag & PARODD)
+ ctrl_val |= ASC_CTL_PARITYODD;
+
+ /* hardware flow control */
+ if ((cflag & CRTSCTS) && ascport->hw_flow_control)
+ ctrl_val |= ASC_CTL_CTSENABLE;
This doesn't reflect those facts back into the termios structure to
indicate that they aren't supported.
Consider using uart_port's ignore and read status masks to implement
the break, framing, parity and overrun checking in your interrupt
handler using the same methodology as drivers like 8250, amba-pl011
etc. That will help you get these code sequences correct.
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-10 09:21:27 UTC
Permalink
From: Stuart Menefy <stuart.menefy-***@public.gmane.org>

This is a simple driver for the global timer module found in the Cortex
A9-MP cores from revision r1p0 onwards. This should be able to perform
the functions of the system timer and the local timer in an SMP system.

The global timer has the following features:
The global timer is a 64-bit incrementing counter with an
auto-incrementing feature. It continues incrementing after sending
interrupts. The global timer is memory mapped in the private memory
region.
The global timer is accessible to all Cortex-A9 processors in the
cluster. Each Cortex-A9 processor has a private 64-bit comparator that
is used to assert a private interrupt when the global timer has reached
the comparator value. All the Cortex-A9 processors in a design use the
banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
Controller as a Private Peripheral Interrupt. The global timer is
clocked by PERIPHCLK.

Signed-off-by: Stuart Menefy <stuart.menefy-***@public.gmane.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-***@public.gmane.org>
CC: Arnd Bergmann <arnd-***@public.gmane.org>
CC: Rob Herring <robherring2-***@public.gmane.org>
CC: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+***@public.gmane.org>
CC: Will Deacon <will.deacon-***@public.gmane.org>
CC: Thomas Gleixner <tglx-***@public.gmane.org>
---
.../devicetree/bindings/arm/global_timer.txt | 21 ++
drivers/clocksource/Kconfig | 13 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/arm_global_timer.c | 368 ++++++++++++++++++++
4 files changed, 403 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/global_timer.txt
create mode 100644 drivers/clocksource/arm_global_timer.c

diff --git a/Documentation/devicetree/bindings/arm/global_timer.txt b/Documentation/devicetree/bindings/arm/global_timer.txt
new file mode 100644
index 0000000..b64abac
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/global_timer.txt
@@ -0,0 +1,21 @@
+
+* ARM Global Timer
+ Cortex-A9 are often associated with a per-core Global timer.
+
+** Timer node required properties:
+
+- compatible : Should be "arm,cortex-a9-global-timer"
+ Driver supports versions r2p0 and above.
+
+- interrupts : One interrupt to each core
+
+- reg : Specify the base address and the size of the GT timer
+ register window.
+
+Example:
+
+ ***@2c000600 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0x2c000600 0x20>;
+ interrupts = <1 13 0xf01>;
+ };
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index f151c6c..b0c4c42 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -67,6 +67,19 @@ config ARM_ARCH_TIMER
bool
select CLKSRC_OF if OF

+config ARM_GLOBAL_TIMER
+ bool
+ select CLKSRC_OF if OF
+ help
+ This options enables support for the ARM global timer unit
+
+config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
+ bool
+ depends on ARM_GLOBAL_TIMER
+ default y
+ help
+ Use ARM global timer clock source as sched_clock
+
config CLKSRC_METAG_GENERIC
def_bool y if METAG
help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 8d979c7..b2363cb 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -28,4 +28,5 @@ obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o

obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
+obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
new file mode 100644
index 0000000..e4bc4fe
--- /dev/null
+++ b/drivers/clocksource/arm_global_timer.c
@@ -0,0 +1,368 @@
+/*
+ * drivers/clocksource/arm_global_timer.c
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Stuart Menefy <stuart.menefy-***@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/sched_clock.h>
+#include <asm/mach/irq.h>
+#include <asm/cputype.h>
+#include <asm/localtimer.h>
+
+#define GT_COUNTER0 0x00
+#define GT_COUNTER1 0x04
+
+#define GT_CONTROL 0x08
+#define GT_CONTROL_TIMER_ENABLE BIT(0) /* this bit is NOT banked */
+#define GT_CONTROL_COMP_ENABLE BIT(1) /* banked */
+#define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */
+#define GT_CONTROL_AUTO_INC BIT(3) /* banked */
+
+#define GT_INT_STATUS 0x0c
+#define GT_INT_STATUS_EVENT_FLAG BIT(0)
+
+#define GT_COMP0 0x10
+#define GT_COMP1 0x14
+#define GT_AUTO_INC 0x18
+
+/*
+ * We are expecting to be clocked by the ARM peripheral clock.
+ *
+ * Note: it is assumed we are using a prescaler value of zero, so this is
+ * the units for all operations.
+ */
+static void __iomem *gt_base;
+static unsigned long gt_clk_rate;
+static int gt_ppi;
+static struct clock_event_device __percpu **gt_evt;
+static DEFINE_PER_CPU(bool, percpu_init_called);
+static DEFINE_PER_CPU(struct clock_event_device, gt_clockevent);
+
+/*
+ * To get the value from the Global Timer Counter register proceed as follows:
+ * 1. Read the upper 32-bit timer counter register
+ * 2. Read the lower 32-bit timer counter register
+ * 3. Read the upper 32-bit timer counter register again. If the value is
+ * different to the 32-bit upper value read previously, go back to step 2.
+ * Otherwise the 64-bit timer counter value is correct.
+ */
+static u64 gt_counter_read(void)
+{
+ u64 counter;
+ u32 lower;
+ u32 upper, old_upper;
+
+ upper = __raw_readl(gt_base + GT_COUNTER1);
+ do {
+ old_upper = upper;
+ lower = __raw_readl(gt_base + GT_COUNTER0);
+ upper = __raw_readl(gt_base + GT_COUNTER1);
+ } while (upper != old_upper);
+
+ counter = upper;
+ counter <<= 32;
+ counter |= lower;
+ return counter;
+}
+
+/**
+ * To ensure that updates to comparator value register do not set the
+ * Interrupt Status Register proceed as follows:
+ * 1. Clear the Comp Enable bit in the Timer Control Register.
+ * 2. Write the lower 32-bit Comparator Value Register.
+ * 3. Write the upper 32-bit Comparator Value Register.
+ * 4. Set the Comp Enable bit and, if necessary, the IRQ enable bit.
+ */
+static void gt_compare_set(unsigned long delta, int periodic)
+{
+ u64 counter = gt_counter_read();
+ unsigned long ctrl = __raw_readl(gt_base + GT_CONTROL);
+
+ counter += delta;
+ ctrl &= ~(GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE);
+
+ __raw_writel(ctrl, gt_base + GT_CONTROL);
+ __raw_writel(lower_32_bits(counter), gt_base + GT_COMP0);
+ __raw_writel(upper_32_bits(counter), gt_base + GT_COMP1);
+
+ if (periodic) {
+ __raw_writel(delta, gt_base + GT_AUTO_INC);
+ ctrl |= GT_CONTROL_AUTO_INC;
+ }
+
+ ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
+ __raw_writel(ctrl, gt_base + GT_CONTROL);
+}
+
+static void gt_clockevent_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+ unsigned long ctrl;
+
+ ctrl = __raw_readl(gt_base + GT_CONTROL);
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ ctrl &= ~(GT_CONTROL_AUTO_INC);
+ __raw_writel(ctrl, gt_base + GT_CONTROL);
+ break;
+ /* Can not shut down it as enable bit is not banked */
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ ctrl &= ~(GT_CONTROL_COMP_ENABLE |
+ GT_CONTROL_IRQ_ENABLE | GT_CONTROL_AUTO_INC);
+ __raw_writel(ctrl, gt_base + GT_CONTROL);
+ break;
+ default:
+ break;
+ }
+}
+
+static int gt_clockevent_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ gt_compare_set(evt, 0);
+ return 0;
+}
+
+static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+
+ if (__raw_readl(gt_base + GT_INT_STATUS) & GT_INT_STATUS_EVENT_FLAG) {
+ /**
+ * ERRATA 740657( Global Timer can send 2 interrupts for
+ * the same event in single-shot mode)
+ * Workaround:
+ * Either disable single-shot mode.
+ * Or
+ * Modify the Interrupt Handler to avoid the
+ * offending sequence. This is achieved by clearing
+ * the Global Timer flag _after_ having incremented
+ * the Comparator register value to a higher value.
+ */
+ if (!(__raw_readl(gt_base + GT_CONTROL) & GT_CONTROL_AUTO_INC))
+ gt_compare_set(ULONG_MAX, 0);
+
+ __raw_writel(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS);
+
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int __cpuinit gt_clockevents_init(struct clock_event_device *clk)
+{
+ struct clock_event_device **this_cpu_clk;
+ int cpu = smp_processor_id();
+
+ clk->name = "ARM global timer clock event";
+ clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ clk->set_mode = gt_clockevent_set_mode;
+ clk->set_next_event = gt_clockevent_set_next_event;
+ this_cpu_clk = __this_cpu_ptr(gt_evt);
+ *this_cpu_clk = clk;
+ clk->cpumask = cpumask_of(cpu);
+ clk->irq = gt_ppi;
+ clockevents_config_and_register(clk, gt_clk_rate,
+ 0, 0xffffffff);
+ per_cpu(percpu_init_called, cpu) = true;
+ enable_percpu_irq(clk->irq, IRQ_TYPE_NONE);
+ return 0;
+}
+
+static void gt_clockevents_stop(struct clock_event_device *clk)
+{
+ gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+ disable_percpu_irq(clk->irq);
+}
+
+static int __cpuinit gt_clockevents_setup(struct clock_event_device *clk)
+{
+ /* Use existing clock_event for boot cpu */
+ if (per_cpu(percpu_init_called, smp_processor_id()))
+ return 0;
+
+ /* already enabled in gt_clocksource_init. */
+ return gt_clockevents_init(clk);
+}
+
+static cycle_t gt_clocksource_read(struct clocksource *cs)
+{
+ return gt_counter_read();
+}
+
+static struct clocksource gt_clocksource = {
+ .name = "ARM global timer clock source",
+ .rating = 300,
+ .read = gt_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
+static u32 gt_sched_clock_read(void)
+{
+ if (!gt_base)
+ return 0;
+
+ return gt_counter_read();
+}
+#endif
+
+static void __init gt_clocksource_init(void)
+{
+ __raw_writel(0, gt_base + GT_CONTROL);
+ __raw_writel(0, gt_base + GT_COUNTER0);
+ __raw_writel(0, gt_base + GT_COUNTER1);
+ /* enables timer on all the cores */
+ __raw_writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
+
+#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
+ setup_sched_clock(gt_sched_clock_read, 32, gt_clk_rate);
+#endif
+ clocksource_register_hz(&gt_clocksource, gt_clk_rate);
+}
+
+static struct clk *gt_get_clock(void)
+{
+ struct clk *clk;
+ int err;
+
+ clk = clk_get_sys("gt", NULL);
+ if (IS_ERR(clk)) {
+ pr_err("global-timer: clock not found: %ld\n", PTR_ERR(clk));
+ return clk;
+ }
+
+ err = clk_prepare_enable(clk);
+ if (err) {
+ pr_err("global-timer: clock prepare+enable failed: %d\n", err);
+ clk_put(clk);
+ return ERR_PTR(err);
+ }
+
+ return clk;
+}
+
+static struct local_timer_ops gt_lt_ops __cpuinitdata = {
+ .setup = gt_clockevents_setup,
+ .stop = gt_clockevents_stop,
+};
+
+int __init global_timer_init(void __iomem *base, unsigned int timer_irq)
+{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *evt = &per_cpu(gt_clockevent, cpu);
+ int err = 0;
+ struct clk *gt_clk;
+
+ if (gt_base) {
+ pr_warn("global-timer: invalid base address\n");
+ return -EINVAL;
+ }
+
+ gt_clk = gt_get_clock();
+ if (IS_ERR(gt_clk)) {
+ pr_warn("global-timer: clk not found\n");
+ return -EINVAL;
+ }
+
+ gt_evt = alloc_percpu(struct clock_event_device *);
+ if (!gt_evt) {
+ pr_warn("global-timer: can't allocate memory\n");
+ return -ENOMEM;
+ }
+
+ err = request_percpu_irq(timer_irq, gt_clockevent_interrupt,
+ "gt", gt_evt);
+ if (err) {
+ pr_warn("global-timer: can't register interrupt %d (%d)\n",
+ timer_irq, err);
+ goto out_free;
+ }
+
+ gt_base = base;
+ gt_clk_rate = clk_get_rate(gt_clk);
+ gt_ppi = timer_irq;
+ gt_clocksource_init();
+ gt_clockevents_init(evt);
+#ifdef CONFIG_LOCAL_TIMERS
+ err = local_timer_register(&gt_lt_ops);
+ if (err) {
+ pr_warn("global-timer: unable to register local timer.\n");
+ goto out_irq;
+ }
+#endif
+ return 0;
+
+out_irq:
+ free_percpu_irq(timer_irq, gt_evt);
+out_free:
+ free_percpu(gt_evt);
+ return err;
+}
+
+#ifdef CONFIG_OF
+static void __init global_timer_of_register(struct device_node *np)
+{
+ struct clk *clk;
+ int err = 0;
+ int gt_ppi;
+ static void __iomem *gt_base;
+
+ /*
+ * In r2p0 the comparators for each processor with the global timer
+ * fire when the timer value is greater than or equal to. In previous
+ * revisions the comparators fired when the timer value was equal to.
+ */
+ if ((read_cpuid_id() & 0xf0000f) < 0x200000)
+ goto out;
+
+ gt_ppi = irq_of_parse_and_map(np, 0);
+ if (!gt_ppi) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ gt_base = of_iomap(np, 0);
+ if (!gt_base) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk))
+ clk_register_clkdev(clk, NULL, "gt");
+
+ global_timer_init(gt_base, gt_ppi);
+
+out:
+ WARN(err, "Global timer register failed (%d)\n", err);
+}
+
+/* Only tested on r2p2 and r3p0 */
+CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",
+ global_timer_of_register);
+#endif
--
1.7.6.5
Linus Walleij
2013-06-10 13:13:34 UTC
Permalink
On Mon, Jun 10, 2013 at 11:21 AM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This is a simple driver for the global timer module found in the Cortex
A9-MP cores from revision r1p0 onwards. This should be able to perform
the functions of the system timer and the local timer in an SMP system.
The global timer is a 64-bit incrementing counter with an
auto-incrementing feature. It continues incrementing after sending
interrupts. The global timer is memory mapped in the private memory
region.
The global timer is accessible to all Cortex-A9 processors in the
cluster. Each Cortex-A9 processor has a private 64-bit comparator that
is used to assert a private interrupt when the global timer has reached
the comparator value. All the Cortex-A9 processors in a design use the
banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
Controller as a Private Peripheral Interrupt. The global timer is
clocked by PERIPHCLK.
This is starting to look very good!

(...)
Post by Srinivas KANDAGATLA
+static int __cpuinit gt_clockevents_init(struct clock_event_device *clk)
+{
+ struct clock_event_device **this_cpu_clk;
+ int cpu = smp_processor_id();
+
+ clk->name = "ARM global timer clock event";
+ clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ clk->set_mode = gt_clockevent_set_mode;
+ clk->set_next_event = gt_clockevent_set_next_event;
+ this_cpu_clk = __this_cpu_ptr(gt_evt);
+ *this_cpu_clk = clk;
+ clk->cpumask = cpumask_of(cpu);
+ clk->irq = gt_ppi;
+ clockevents_config_and_register(clk, gt_clk_rate,
+ 0, 0xffffffff);
What do you mean with being able to set event on
0?

This should most probably be:


clockevents_config_and_register(clk, gt_clk_rate,
1, 0xffffffff);

(...)
Post by Srinivas KANDAGATLA
+static struct clk *gt_get_clock(void)
+{
+ struct clk *clk;
+ int err;
+
+ clk = clk_get_sys("gt", NULL);
+ if (IS_ERR(clk)) {
+ pr_err("global-timer: clock not found: %ld\n", PTR_ERR(clk));
+ return clk;
+ }
(...)
Post by Srinivas KANDAGATLA
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk))
+ clk_register_clkdev(clk, NULL, "gt");
Well that was clever.

Isn't it better to pass a struct device_node *np around and have that as
NULL in the non-DT boot path?

(Maybe somebody in the community asked you to do this, then I
will live with it.)

Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-10 13:41:58 UTC
Permalink
Post by Linus Walleij
On Mon, Jun 10, 2013 at 11:21 AM, Srinivas KANDAGATLA
This is starting to look very good!
(...)
Thankyou.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+static int __cpuinit gt_clockevents_init(struct clock_event_device *clk)
+{
+ struct clock_event_device **this_cpu_clk;
+ int cpu = smp_processor_id();
+
+ clk->name = "ARM global timer clock event";
+ clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ clk->set_mode = gt_clockevent_set_mode;
+ clk->set_next_event = gt_clockevent_set_next_event;
+ this_cpu_clk = __this_cpu_ptr(gt_evt);
+ *this_cpu_clk = clk;
+ clk->cpumask = cpumask_of(cpu);
+ clk->irq = gt_ppi;
+ clockevents_config_and_register(clk, gt_clk_rate,
+ 0, 0xffffffff);
What do you mean with being able to set event on
0?
Its a bit of over do from me.. I will change it to what you suggested...
Post by Linus Walleij
clockevents_config_and_register(clk, gt_clk_rate,
1, 0xffffffff);
(...)
Post by Srinivas KANDAGATLA
+static struct clk *gt_get_clock(void)
+{
+ struct clk *clk;
+ int err;
+
+ clk = clk_get_sys("gt", NULL);
+ if (IS_ERR(clk)) {
+ pr_err("global-timer: clock not found: %ld\n", PTR_ERR(clk));
+ return clk;
+ }
(...)
Post by Srinivas KANDAGATLA
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk))
+ clk_register_clkdev(clk, NULL, "gt");
Well that was clever.
Isn't it better to pass a struct device_node *np around and have that as
NULL in the non-DT boot path?
I will try it and see how it will look.

Thanks,
srini
Post by Linus Walleij
(Maybe somebody in the community asked you to do this, then I
will live with it.)
Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-11 14:05:14 UTC
Permalink
Post by Srinivas KANDAGATLA
Post by Linus Walleij
On Mon, Jun 10, 2013 at 11:21 AM, Srinivas KANDAGATLA
Isn't it better to pass a struct device_node *np around and have that as
NULL in the non-DT boot path?
I will try it and see how it will look.
I did try the change you suggested regarding passing struct device_node
*np around for both DT and non-DT boot paths.

Doing this is not adding any value to the driver, because
1. Currently the driver only support DT boot paths, in my previous RFC
patches, Arnd suggested to get rid of the header as all platforms are DT
now.
2. Passing device_node around is not adding any value w.r.t reducing
code or any thing.

So, I think I will stay with what is there originally, unless you have a
strong reason.

Thanks,
srini
Post by Srinivas KANDAGATLA
Thanks,
srini
Post by Linus Walleij
(Maybe somebody in the community asked you to do this, then I
will live with it.)
Yours,
Linus Walleij
Linus Walleij
2013-06-11 20:13:04 UTC
Permalink
On Tue, Jun 11, 2013 at 4:05 PM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
Doing this is not adding any value to the driver, because
1. Currently the driver only support DT boot paths, in my previous RFC
patches, Arnd suggested to get rid of the header as all platforms are DT
now.
In that case why do you have the separate global_timer_init()
at all? Just move that code into global_timer_of_register() and
also remove the #ifdef around CONFIG_OF and make the driver
depend on CONFIG_OF in Kconfig.

After this you realize that all that business with
clk_register_clkdev() / clk_get_sys() is just pure surplus
baggade, you just use of_clk_get() and that's it.

Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-12 10:45:37 UTC
Permalink
Post by Linus Walleij
On Tue, Jun 11, 2013 at 4:05 PM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
Doing this is not adding any value to the driver, because
1. Currently the driver only support DT boot paths, in my previous RFC
patches, Arnd suggested to get rid of the header as all platforms are DT
now.
In that case why do you have the separate global_timer_init()
at all? Just move that code into global_timer_of_register() and
also remove the #ifdef around CONFIG_OF and make the driver
depend on CONFIG_OF in Kconfig.
After this you realize that all that business with
clk_register_clkdev() / clk_get_sys() is just pure surplus
baggade, you just use of_clk_get() and that's it.
It makes sense to move all the code into global_timer_of_register().
This will also get rid of un-used code. I will do this in the next spin.

Thanks,
srini
Post by Linus Walleij
Yours,
Linus Walleij
_______________________________________________
devicetree-discuss mailing list
https://lists.ozlabs.org/listinfo/devicetree-discuss
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-10 09:22:27 UTC
Permalink
System configuration(aka syscfg) registers are very basic configuration
registers arranged in groups across ST Settop Box parts.

The SOCs are assembled from existing IP blocks, which don't change very
often. However these blocks are assembled in different configurations to
meet the device requirements. So most IP blocks as well as having a bus
interface through which their own registers are accessible, will also
have a number of bristles(wires) which are signals that are going in and
out of the IP for configuration and status. To make these signals
accessible to software they are wired to "System Configuration
Registers".

Drivers target the IP blocks, which don't change much. Where as the
mapping of IP specific bristles(wires) to "System Configuration
Registers" do change per each SOC, and therefore we do not want this
information to be part of the driver.

Having a System Configuration infrastructure gives much flexibility and
abstraction to drivers to configure them. Typically in a SOC there will
be more than hundreds of these registers, which are again divided into
groups. The IP related config registers tend to much regular in latest
ST SOCs, so having a common place for configuring these registers makes
sense and avoid lot of code duplication.

This mfd driver provides higher level inialization routines for various
IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
get to syscfg registers via standard regmap api which is usefull for
drivers like pinctrl.

This patch adds support to ST System Configuration registers, which can
be configured by the drivers.

Signed-off-by: Srinivas Kandagatla <***@st.com>
CC: Stuart Menefy <***@st.com>
CC: Stephen Gallimore <***@st.com>
CC: Linus Walleij <***@linaro.org>
CC: Mark Brown <***@kernel.org>
---
.../devicetree/bindings/mfd/stixxxx-syscfg.txt | 18 ++
drivers/mfd/Kconfig | 10 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/stixxxx-syscfg.c | 168 ++++++++++++++++++++
include/linux/mfd/stixxxx-syscfg.h | 15 ++
5 files changed, 212 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
create mode 100644 drivers/mfd/stixxxx-syscfg.c
create mode 100644 include/linux/mfd/stixxxx-syscfg.h

diff --git a/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt b/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
new file mode 100644
index 0000000..428c751
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
@@ -0,0 +1,18 @@
+*STixxxx SYSCFG
+
+- compatible : should be "st,<SOC>-syscfg" like "st,stih415-syscfg"
+ or "st,stih416-syscfg".
+- reg, reg-names, interrupts, interrupt-names : Standard way to define device
+ resources with names. look in
+ Documentation/devicetree/bindings/resource-names.txt
+- syscfg-range <start size> : Should be syscfg number range for this bank.
+- syscfg-name : Should be name of the syscfg, will be used in debugfs.
+
+Example of a SBC_SYSCFG bank node:
+
+syscfg_sbc: ***@fe600000{
+ compatible = "st,stih415-syscfg";
+ reg = <0xfe600000 0xb4>;
+ syscfg-range = <0 44>;
+ syscfg-name = "SYSCFG_SBC";
+};
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index d54e985..af49b58 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -649,6 +649,16 @@ config MFD_STA2X11
select MFD_CORE
select REGMAP_MMIO

+config MFD_STIXXXX_SYSCFG
+ bool "ST System Configuration Registers(aka syscfg) via regmap"
+ select REGMAP_MMIO
+ help
+ Select this option to enable accessing STMicroelectronics
+ System Configuration Registers via standard regmap apis with
+ lookup helper functions.
+
+ If unsure, say N.
+
config MFD_SYSCON
bool "System Controller Register R/W Based on Regmap"
select REGMAP_MMIO
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 718e94a..c1f6570 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -150,6 +150,7 @@ obj-$(CONFIG_MFD_PALMAS) += palmas.o
obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
+obj-$(CONFIG_MFD_STIXXXX_SYSCFG) += stixxxx-syscfg.o
obj-$(CONFIG_MFD_SYSCON) += syscon.o
obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o vexpress-sysreg.o
diff --git a/drivers/mfd/stixxxx-syscfg.c b/drivers/mfd/stixxxx-syscfg.c
new file mode 100644
index 0000000..10ea4e4
--- /dev/null
+++ b/drivers/mfd/stixxxx-syscfg.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics Limited
+ * Author: Srinivas Kandagatla <***@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Syscfg driver is used to configure various devices like Ethernet,
+ * USB, PCIE, SATA and so on.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/mfd/stixxxx-syscfg.h>
+
+#define DRIVER_NAME "stixxxx-syscfg"
+
+static struct platform_driver syscfg_driver;
+struct syscfg {
+ void __iomem *base;
+ struct regmap *regmap;
+ int start, end;
+ const char *name;
+ struct device_node *of_node;
+};
+
+static int syscfg_match_name(struct device *dev, void *data)
+{
+ struct syscfg *syscfg = dev_get_drvdata(dev);
+
+ if (syscfg)
+ if (!strcmp(syscfg->name, (const char *)data))
+ return 1;
+ return 0;
+}
+
+struct regmap *syscfg_regmap_lookup_by_name(const char *name)
+{
+ struct syscfg *syscfg;
+ struct device *dev;
+
+ dev = driver_find_device(&syscfg_driver.driver, NULL, (void *)name,
+ syscfg_match_name);
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ syscfg = dev_get_drvdata(dev);
+
+ return syscfg->regmap;
+}
+
+static int syscfg_match_node(struct device *dev, void *data)
+{
+ struct device_node *dn = data;
+
+ return (dev->of_node == dn) ? 1 : 0;
+}
+
+struct regmap *syscfg_node_to_regmap(struct device_node *np)
+{
+ struct syscfg *syscfg;
+ struct device *dev;
+
+ dev = driver_find_device(&syscfg_driver.driver, NULL, np,
+ syscfg_match_node);
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ syscfg = dev_get_drvdata(dev);
+
+ return syscfg->regmap;
+}
+EXPORT_SYMBOL_GPL(syscfg_node_to_regmap);
+
+struct regmap *syscfg_regmap_lookup_by_phandle(struct device_node *np,
+ const char *property)
+{
+ struct device_node *syscfg_np;
+ struct regmap *regmap;
+
+ syscfg_np = of_parse_phandle(np, property, 0);
+ if (!syscfg_np)
+ return ERR_PTR(-ENODEV);
+
+ regmap = syscfg_node_to_regmap(syscfg_np);
+ of_node_put(syscfg_np);
+
+ return regmap;
+}
+EXPORT_SYMBOL_GPL(syscfg_regmap_lookup_by_phandle);
+
+static struct regmap_config syscfg_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int syscfg_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct syscfg *syscfg;
+ struct resource *res;
+ u32 range[2];
+
+ if (!np)
+ return -EINVAL;
+
+ syscfg = devm_kzalloc(&pdev->dev, sizeof(*syscfg), GFP_KERNEL);
+ if (!syscfg)
+ return -ENOMEM;
+
+ syscfg->of_node = np;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ syscfg->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!syscfg->base) {
+ dev_err(&pdev->dev, "Unable to ioremap registers|\n");
+ return -ENODATA;
+ }
+
+ of_property_read_u32_array(np, "syscfg-range", (u32 *)&range, 2);
+ syscfg->start = range[0];
+ syscfg->end = range[0] + range[1];
+ of_property_read_string(np, "syscfg-name", &syscfg->name);
+
+ syscfg_regmap_config.name = kasprintf(GFP_KERNEL, "%s", syscfg->name);
+ syscfg_regmap_config.max_register = res->end - res->start - 3;
+ syscfg->regmap = devm_regmap_init_mmio(&pdev->dev, syscfg->base,
+ &syscfg_regmap_config);
+ if (IS_ERR(syscfg->regmap)) {
+ dev_err(&pdev->dev, "regmap init failed\n");
+ return PTR_ERR(syscfg->regmap);
+ }
+
+ platform_set_drvdata(pdev, syscfg);
+ dev_info(&pdev->dev,
+ "%s[%d - %d] sucessfully intialized\n",
+ syscfg->name, syscfg->start, syscfg->end);
+ return 0;
+}
+
+static struct of_device_id syscfg_match[] = {
+ { .compatible = "st,stih415-syscfg", },
+ { .compatible = "st,stih416-syscfg", },
+ {},
+};
+
+static struct platform_driver syscfg_driver = {
+ .probe = syscfg_probe,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(syscfg_match),
+ },
+};
+
+static int __init syscfg_init(void)
+{
+ return platform_driver_register(&syscfg_driver);
+}
+postcore_initcall(syscfg_init);
diff --git a/include/linux/mfd/stixxxx-syscfg.h b/include/linux/mfd/stixxxx-syscfg.h
new file mode 100644
index 0000000..18ed6da7
--- /dev/null
+++ b/include/linux/mfd/stixxxx-syscfg.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics R&D Limited
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ */
+
+#ifndef __LINUX_MFD_STIXXXX_SYSCFG_H
+#define __LINUX_MFD_STIXXXX_SYSCFG_H
+
+struct regmap *syscfg_regmap_lookup_by_phandle(struct device_node *np,
+ const char *property);
+struct regmap *syscfg_regmap_lookup_by_name(const char *name);
+
+#endif /* __LINUX_MFD_STIXXXX_SYSCFG_H */
--
1.7.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Linus Walleij
2013-06-10 13:16:34 UTC
Permalink
On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This mfd driver provides higher level inialization routines for various
IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
get to syscfg registers via standard regmap api which is usefull for
drivers like pinctrl.
This patch adds support to ST System Configuration registers, which can
be configured by the drivers.
What is this driver doing that drivers/mfd/syscon.c is not already
doing?

I just get the feeling that you're reinventing the wheel here.

Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-10 13:52:38 UTC
Permalink
Post by Linus Walleij
On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This mfd driver provides higher level inialization routines for various
IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
get to syscfg registers via standard regmap api which is usefull for
drivers like pinctrl.
This patch adds support to ST System Configuration registers, which can
be configured by the drivers.
What is this driver doing that drivers/mfd/syscon.c is not already
doing?
As of now, the driver is very much similar to syscon + some additional
functionality, but we are planning to use this file to add higher level
functions to configure different IPs like ethernet, usb, power, reset
and so on which are very much specific to ST System Configuration Registers.

Thanks,
srini
Post by Linus Walleij
I just get the feeling that you're reinventing the wheel here.
Yours,
Linus Walleij
_______________________________________________
devicetree-discuss mailing list
https://lists.ozlabs.org/listinfo/devicetree-discuss
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Arnd Bergmann
2013-06-10 14:02:04 UTC
Permalink
Post by Srinivas KANDAGATLA
Post by Linus Walleij
On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This mfd driver provides higher level inialization routines for various
IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
get to syscfg registers via standard regmap api which is usefull for
drivers like pinctrl.
This patch adds support to ST System Configuration registers, which can
be configured by the drivers.
What is this driver doing that drivers/mfd/syscon.c is not already
doing?
As of now, the driver is very much similar to syscon + some additional
functionality, but we are planning to use this file to add higher level
functions to configure different IPs like ethernet, usb, power, reset
and so on which are very much specific to ST System Configuration Registers.
I was expecting that you'd actually interface with the syscon code and
build on top, rather than copy it.

There are multiple ways of doing that, e.g. you could export a function
from syscon.c that you call to register the device node and then import
the regmap from syscon into your high-level driver again.

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-10 15:51:41 UTC
Permalink
Thanks for the comments.
Post by Arnd Bergmann
Post by Srinivas KANDAGATLA
Post by Linus Walleij
On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This mfd driver provides higher level inialization routines for various
IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
get to syscfg registers via standard regmap api which is usefull for
drivers like pinctrl.
This patch adds support to ST System Configuration registers, which can
be configured by the drivers.
What is this driver doing that drivers/mfd/syscon.c is not already
doing?
As of now, the driver is very much similar to syscon + some additional
functionality, but we are planning to use this file to add higher level
functions to configure different IPs like ethernet, usb, power, reset
and so on which are very much specific to ST System Configuration Registers.
I was expecting that you'd actually interface with the syscon code and
build on top, rather than copy it.
I did not like the copying either, on the other hand I don't want to
pollute the syscon code.

As you said, I will make use of existing syscon and build "System
configuration interface" on top of it and see how it look like. It will
definitely get rid of lot of code duplication.

Thanks,
srini
Post by Arnd Bergmann
There are multiple ways of doing that, e.g. you could export a function
from syscon.c that you call to register the device node and then import
the regmap from syscon into your high-level driver again.
Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-11 07:41:19 UTC
Permalink
Post by Arnd Bergmann
There are multiple ways of doing that, e.g. you could export a function
from syscon.c that you call to register the device node and then import
the regmap from syscon into your high-level driver again.
Hi Arnd/Linus,

Thankyou for your comments,
I did try using the full sysconf names in compatible and make use of
syscon driver, with this change the nodes look much neater.

The nodes changes to:

syscfg_sbc:***@fe600000{
compatible = "st,stih416-sbc-syscfg", "syscon";
reg = <0xfe600000 0x1000>;
};

From:
syscfg_sbc:***@fe600000{
compatible = "st,stih416-syscfg";
reg = <0xfe600000 0x1000>;
syscfg-range = <0 999>;
syscfg-name = "SYSCFG_SBC";
};


Also I got rid of the drivers/mfd/stixxxx-syscfg.c driver all together
for this basic support patch series, I will add this once there are new
high level functions.
Additional compatible string will allow code to get to regmap via syscon
apis.

I will get rid of this driver in next version for this series.

Thanks,
srini
Post by Arnd Bergmann
Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-10 09:21:58 UTC
Permalink
It is common to access regmap registers at bit level, using
regmap_update_bits or regmap_read functions, however the end user has to
take care of a mask or shifting. This becomes overhead when such use
cases are high. Having a common function to do this is much convenient
and less error prone.

The idea of regmap_field is simple, regmap_field gives a logical
structure to bits of the regmap register, and the driver can use this
logical entity without the knowledge of the bit postions and masks all
over the code. This way code looks much neat and it need not handle the
masks, shifts every time it access the those entities.

With this new regmap_field_read/write apis the end user can setup a
regmap field using regmap_field_init and use the return regmap_field to
read write the register field without worrying about the masks or
shifts.

Also this apis will be usefull for drivers which are based on regmaps,
like some clocks or pinctrls which can work on the regmap_fields
directly without having to worry about bit positions.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-***@public.gmane.org>
CC: Mark Brown <broonie-DgEjT+Ai2ygdnm+***@public.gmane.org>
CC: Arnd Bergmann <arnd-***@public.gmane.org>
CC: Alexander Shiyan <shc_work-JGs/***@public.gmane.org>
CC: Lars-Peter Clausen <lars-Qo5EllUWu/***@public.gmane.org>
---
drivers/base/regmap/internal.h | 8 +++
drivers/base/regmap/regmap.c | 104 ++++++++++++++++++++++++++++++++++++++++
include/linux/regmap.h | 42 ++++++++++++++++
3 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index c130536..c5f6ebd 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -174,6 +174,14 @@ struct regmap_range_node {
unsigned int window_len;
};

+struct regmap_field {
+ struct regmap *regmap;
+ unsigned int mask;
+ /* lsb */
+ unsigned int shift;
+ unsigned int reg;
+};
+
#ifdef CONFIG_DEBUG_FS
extern void regmap_debugfs_initcall(void);
extern void regmap_debugfs_init(struct regmap *map, const char *name);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index a941dcf..8d967cc 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -801,6 +801,67 @@ struct regmap *devm_regmap_init(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_regmap_init);

+static void regmap_field_init(struct regmap_field *rm_field,
+ struct regmap *regmap, struct reg_field reg_field)
+{
+ int field_bits = reg_field.msb - reg_field.lsb + 1;
+ rm_field->regmap = regmap;
+ rm_field->reg = reg_field.reg;
+ rm_field->shift = reg_field.lsb;
+ rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
+}
+
+/**
+ * devm_regmap_field_alloc(): Allocate and initialise a register field
+ * in a register map.
+ *
+ * @dev: Device that will be interacted with
+ * @regmap: regmap bank in which this register field is located.
+ * @reg_field: Register field with in the bank.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap_field. The regmap_field will be automatically freed
+ * by the device management code.
+ */
+struct regmap_field *devm_regmap_field_alloc(struct device *dev,
+ struct regmap *regmap, struct reg_field reg_field)
+{
+ struct regmap_field *rm_field = devm_kzalloc(dev,
+ sizeof(*rm_field), GFP_KERNEL);
+ if (!rm_field)
+ return ERR_PTR(-ENOMEM);
+
+ regmap_field_init(rm_field, regmap, reg_field);
+
+ return rm_field;
+
+}
+EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
+/**
+ * regmap_field_alloc(): Allocate and initialise a register field
+ * in a register map.
+ *
+ * @regmap: regmap bank in which this register field is located.
+ * @reg_field: Register field with in the bank.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap_field. The regmap_field should be freed by the
+ * user once its finished working with it using regmap_field_free().
+ */
+struct regmap_field *regmap_field_alloc(struct regmap *regmap,
+ struct reg_field reg_field)
+{
+ struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
+
+ if (!rm_field)
+ return ERR_PTR(-ENOMEM);
+
+ regmap_field_init(rm_field, regmap, reg_field);
+
+ return rm_field;
+}
+EXPORT_SYMBOL_GPL(regmap_field_alloc);
+
/**
* regmap_reinit_cache(): Reinitialise the current register cache
*
@@ -1249,6 +1310,23 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
}
EXPORT_SYMBOL_GPL(regmap_raw_write);

+/**
+ * regmap_field_write(): Write a value to a single register field
+ *
+ * @field: Register field to write to
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+
+int regmap_field_write(struct regmap_field *field, unsigned int val)
+{
+ return regmap_update_bits(field->regmap, field->reg,
+ field->mask, val << field->shift);
+}
+EXPORT_SYMBOL_GPL(regmap_field_write);
+
/*
* regmap_bulk_write(): Write multiple registers to the device
*
@@ -1532,6 +1610,32 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
EXPORT_SYMBOL_GPL(regmap_raw_read);

/**
+ * regmap_field_read(): Read a value to a single register field
+ *
+ * @field: Register field to read from
+ * @val: Pointer to store read value
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+
+int regmap_field_read(struct regmap_field *field, unsigned int *val)
+{
+ int ret;
+ unsigned int reg_val;
+ ret = regmap_read(field->regmap, field->reg, &reg_val);
+ if (ret != 0)
+ return ret;
+
+ reg_val &= field->mask;
+ reg_val >>= field->shift;
+ *val = reg_val;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_field_read);
+
+/**
* regmap_bulk_read(): Read multiple registers from the device
*
* @map: Register map to write to
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 02d84e2..557a54e 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -15,6 +15,8 @@

#include <linux/list.h>
#include <linux/rbtree.h>
+#include <linux/device.h>
+#include <linux/slab.h>

struct module;
struct device;
@@ -23,6 +25,7 @@ struct irq_domain;
struct spi_device;
struct regmap;
struct regmap_range_cfg;
+struct regmap_field;

/* An enum of all the supported cache types */
enum regcache_type {
@@ -412,6 +415,45 @@ bool regmap_reg_in_ranges(unsigned int reg,
unsigned int nranges);

/**
+ * Description of an register field
+ *
+ * @reg: Offset of the register within the regmap bank
+ * @lsb: lsb of the register field.
+ * @reg: msb of the register field.
+ */
+struct reg_field {
+ unsigned int reg;
+ unsigned int lsb;
+ unsigned int msb;
+};
+
+#define REG_FIELD(_reg, _lsb, _msb) { \
+ .reg = _reg, \
+ .lsb = _lsb, \
+ .msb = _msb, \
+ }
+
+struct regmap_field *regmap_field_alloc(struct regmap *regmap,
+ struct reg_field reg_field);
+
+struct regmap_field *devm_regmap_field_alloc(struct device *dev,
+ struct regmap *regmap, struct reg_field reg_field);
+
+static inline void regmap_field_free(struct regmap_field *field)
+{
+ kfree(field);
+}
+
+static inline void devm_regmap_field_free(struct device *dev,
+ struct regmap_field *field)
+{
+ devm_kfree(dev, field);
+}
+
+int regmap_field_read(struct regmap_field *field, unsigned int *val);
+int regmap_field_write(struct regmap_field *field, unsigned int val);
+
+/**
* Description of an IRQ for the generic regmap irq_chip.
*
* @reg_offset: Offset of the status/mask register within the bank
--
1.7.6.5
Mark Brown
2013-06-11 10:48:41 UTC
Permalink
Post by Srinivas KANDAGATLA
It is common to access regmap registers at bit level, using
regmap_update_bits or regmap_read functions, however the end user has to
take care of a mask or shifting. This becomes overhead when such use
cases are high. Having a common function to do this is much convenient
and less error prone.
So this looks basically good. A couple of smallish nits below, if you
could respin I'll apply this on a branch so it can be pulled in as
dependency for the other things that use it.
Post by Srinivas KANDAGATLA
+ regmap_field_init(rm_field, regmap, reg_field);
+
+ return rm_field;
+
+}
+EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
+/**
+ * regmap_field_alloc(): Allocate and initialise a register field
Needs a blank line between the two functions.
Post by Srinivas KANDAGATLA
+#include <linux/device.h>
+#include <linux/slab.h>
+static inline void regmap_field_free(struct regmap_field *field)
+{
+ kfree(field);
+}
+static inline void devm_regmap_field_free(struct device *dev,
+ struct regmap_field *field)
+{
+ devm_kfree(dev, field);
+}
Probably not worth inlining these, just put them in the code.
Srinivas KANDAGATLA
2013-06-11 11:36:17 UTC
Permalink
Post by Mark Brown
Post by Srinivas KANDAGATLA
It is common to access regmap registers at bit level, using
regmap_update_bits or regmap_read functions, however the end user has to
take care of a mask or shifting. This becomes overhead when such use
cases are high. Having a common function to do this is much convenient
and less error prone.
So this looks basically good. A couple of smallish nits below, if you
could respin I'll apply this on a branch so it can be pulled in as
dependency for the other things that use it.
Thankyou for the comments,
I will fix it and send a v3 patch.
Post by Mark Brown
Post by Srinivas KANDAGATLA
+ regmap_field_init(rm_field, regmap, reg_field);
+
+ return rm_field;
+
+}
+EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
+/**
+ * regmap_field_alloc(): Allocate and initialise a register field
Needs a blank line between the two functions.
Post by Srinivas KANDAGATLA
+#include <linux/device.h>
+#include <linux/slab.h>
+static inline void regmap_field_free(struct regmap_field *field)
+{
+ kfree(field);
+}
+static inline void devm_regmap_field_free(struct device *dev,
+ struct regmap_field *field)
+{
+ devm_kfree(dev, field);
+}
Probably not worth inlining these, just put them in the code.
_______________________________________________
devicetree-discuss mailing list
https://lists.ozlabs.org/listinfo/devicetree-discuss
Srinivas KANDAGATLA
2013-06-10 09:22:41 UTC
Permalink
This patch add pinctrl support to ST SoCs.

About hardware:
ST Set-Top-Box parts have two blocks called PIO and PIO-mux which handle
pin configurations.

Each multi-function pin is controlled, driven and routed through the PIO
multiplexing block. Each pin supports GPIO functionality (ALT0) and
multiple alternate functions(ALT1 - ALTx) that directly connect the pin
to different hardware blocks. When a pin is in GPIO mode, Output Enable
(OE), Open Drain(OD), and Pull Up (PU) are driven by the related PIO
block. Otherwise the PIO multiplexing block configures these parameters
and retiming the signal.

About driver:
This pinctrl driver manages both PIO and PIO-mux block using pinctrl,
pinconf, pinmux, gpio subsystems. All the pinctrl related config
information can only come from device trees.

Signed-off-by: Srinivas Kandagatla <***@st.com>
CC: Stephen Gallimore <***@st.com>
CC: Stuart Menefy <***@st.com>
CC: Arnd Bergmann <***@arndb.de>
CC: Linus Walleij <***@linaro.org>
---
.../bindings/pinctrl/pinctrl-stixxxx.txt | 116 ++
drivers/pinctrl/Kconfig | 11 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-stixxxx.c | 1212 ++++++++++++++++++++
drivers/pinctrl/pinctrl-stixxxx.h | 197 ++++
5 files changed, 1537 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
create mode 100644 drivers/pinctrl/pinctrl-stixxxx.c
create mode 100644 drivers/pinctrl/pinctrl-stixxxx.h

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
new file mode 100644
index 0000000..ac69dca
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
@@ -0,0 +1,116 @@
+*ST pin controller.
+
+Each multi-function pin is controlled, driven and routed through the
+PIO multiplexing block. Each pin supports GPIO functionality (ALT0)
+and multiple alternate functions(ALT1 - ALTx) that directly connect
+the pin to different hardware blocks.
+
+When a pin is in GPIO mode, Output Enable (OE), Open Drain(OD), and
+Pull Up (PU) are driven by the related PIO block.
+
+ST pinctrl driver controls PIO multiplexing block and also interacts with
+gpio driver to configure a pin.
+
+Required properties: (PIO multiplexing block)
+- compatible : should be "st,stixxxx-pinctrl"
+ each subnode should set "st,stixxxx-gpio"
+ as compatible for each gpio-controller bank.
+- gpio-controller : Indicates this device is a GPIO controller
+- #gpio-cells : Should be one. The first cell is the pin number.
+- st,retime-in-delay : Should be array of delays in nsecs.
+- st,retime-out-delay : Should be array of delays in nsecs.
+- st,retime-pin-mask : Should be mask to specify which pins can be retimed.
+- st,bank-name : Should be a name string for this bank.
+- st,syscfg : phandle of the syscfg node.
+- st,syscfg-offsets : Should be a 5 cell entry which represent offset of altfunc,
+ output-enable, pull-up , open drain and retime registers in the syscfg bank
+
+Example:
+ pin-controller {
+ compatible = "st,stixxxx-pinctrl", "simple-bus";
+ st,retime-in-delay = <0 500 1000 1500>;
+ st,retime-out-delay = <0 1000 2000 3000>;
+ st,syscfg = <&syscfg_front>;
+ st,syscfg-offsets = <0 8 10 12 16>;
+ ranges;
+ PIO0: ***@fe610000 {
+ gpio-controller;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ reg = <0xfe610000 0x100>;
+ st,bank-name = "PIO0";
+ };
+ ...
+ pin-functions nodes follow...
+ };
+
+
+Contents of function subnode node:
+----------------------
+Required properties for pin configuration node:
+- st,function : Should be alternate function number associated
+ with this set of pins. Use same numbers from datasheet.
+
+- st,pins : Child node with list of pins with configuration.
+
+Below is the format of how each pin conf should look like.
+
+<bank offset mode rt_type rt_delay rt_clk>
+
+Every PIO is represented with 4-7 parameters depending on retime configuration.
+Each parameter is explained as below.
+
+-bank : Should be bank phandle to which this PIO belongs.
+-offset : Offset in the PIO bank.
+-mode :pin configuration is selected from one of the below values.
+ IN
+ IN_PU
+ OUT
+ BIDIR
+ BIDIR_PU
+
+-rt_type Retiming Configuration for the pin.
+ Possible retime configuration are:
+
+ ------- -------------
+ value args
+ ------- -------------
+ NICLK <delay> <clk>
+ ICLK_IO <delay> <clk>
+ BYPASS <delay>
+ DE_IO <delay> <clk>
+ SE_ICLK_IO <delay> <clk>
+ SE_NICLK_IO <delay> <clk>
+
+- delay is retime delay in pico seconds.
+ Possible values are: refer to retime-in/out-delays
+
+- rt_clk :clk to be use for retime.
+ Possible values are:
+ CLK_A
+ CLK_B
+ CLK_C
+ CLK_D
+
+Example of mmcclk pin which is a bi-direction pull pu with retime config
+as non inverted clock retimed with CLK_B and delay of 0 pico seconds:
+
+pin-controller {
+ ...
+ mmc0 {
+ pinctrl_mmc: mmc {
+ st,function = <ALT4>;
+ st,pins {
+ mmcclk = <&PIO13 4 BIDIR_PU NICLK 0 CLK_B>;
+ ...
+ };
+ };
+ ...
+ };
+};
+
+sdhci0:***@fe810000{
+ ...
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mmc>;
+};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 8f66924..0c040a3 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -169,6 +169,17 @@ config PINCTRL_SUNXI
select PINMUX
select GENERIC_PINCONF

+config PINCTRL_STIXXXX
+ bool "ST Microelectronics pin controller driver for STixxxx SoCs"
+ select PINMUX
+ select PINCONF
+ help
+ Say yes here to support pinctrl interface on STixxxx SOCs.
+ This driver is used to control both PIO block and PIO-mux
+ block to configure a pin.
+
+ If unsure, say N.
+
config PINCTRL_TEGRA
bool
select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 9bdaeb8..0e035bb 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o
obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
+obj-$(CONFIG_PINCTRL_STIXXXX) += pinctrl-stixxxx.o

obj-$(CONFIG_PLAT_ORION) += mvebu/
obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
diff --git a/drivers/pinctrl/pinctrl-stixxxx.c b/drivers/pinctrl/pinctrl-stixxxx.c
new file mode 100644
index 0000000..da4e3d7
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-stixxxx.c
@@ -0,0 +1,1212 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Authors:
+ * Srinivas Kandagatla <***@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/stixxxx-syscfg.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/platform_device.h>
+#include "core.h"
+#include "pinctrl-stixxxx.h"
+
+struct stixxxx_pinconf {
+ int pin;
+ const char *name;
+ unsigned long config;
+};
+
+struct stixxxx_pmx_func {
+ const char *name;
+ const char **groups;
+ unsigned ngroups;
+};
+
+struct stixxxx_pctl_group {
+ const char *name;
+ unsigned int *pins;
+ unsigned npins;
+ int altfunc;
+ struct stixxxx_pinconf *pin_conf;
+};
+
+#define to_stixxxx_gpio_port(chip) \
+ container_of(chip, struct stixxxx_gpio_port, gpio_chip)
+
+struct stixxxx_gpio_port {
+ struct gpio_chip gpio_chip;
+ struct pinctrl_gpio_range range;
+ void __iomem *base;
+ struct device_node *of_node;
+ const char *bank_name;
+};
+
+static struct stixxxx_gpio_port *gpio_ports[STIXXXX_MAX_GPIO_BANKS];
+
+struct stixxxx_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ int nbanks;
+ struct stixxxx_pmx_func *functions;
+ int nfunctions;
+ struct stixxxx_pctl_group *groups;
+ int ngroups;
+ struct stixxxx_pio_control *pio_controls;
+ struct pinctrl_gpio_range **gpio_ranges;
+ struct regmap *regmap;
+};
+
+/* Low level functions.. */
+static void stixxxx_pinconf_set_direction(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long config)
+{
+ struct regmap_field *output_enable;
+ struct regmap_field *pull_up;
+ struct regmap_field *open_drain;
+ unsigned int oe_value, pu_value, od_value;
+ unsigned long mask;
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ output_enable = pc->oe;
+ pull_up = pc->pu;
+ open_drain = pc->od;
+
+ mask = BIT(pin);
+
+ regmap_field_read(output_enable, &oe_value);
+ regmap_field_read(pull_up, &pu_value);
+ regmap_field_read(open_drain, &od_value);
+
+ /* Clear old values */
+ oe_value &= ~mask;
+ pu_value &= ~mask;
+ od_value &= ~mask;
+
+ if (config & STIXXXX_PINCONF_OE)
+ oe_value |= mask;
+ if (config & STIXXXX_PINCONF_PU)
+ pu_value |= mask;
+ if (config & STIXXXX_PINCONF_OD)
+ od_value |= mask;
+
+ regmap_field_write(output_enable, oe_value);
+ regmap_field_write(pull_up, pu_value);
+ regmap_field_write(open_drain, od_value);
+}
+
+static void stixxxx_pctl_set_function(struct stixxxx_pio_control *pc,
+ int pin_id, int function)
+{
+ struct regmap_field *selector;
+ int offset;
+ unsigned int val;
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ selector = pc->alt;
+ offset = pin * 4;
+ regmap_field_read(selector, &val);
+ val &= ~(0xf << offset);
+ val |= function << offset;
+ regmap_field_write(selector, val);
+}
+
+static unsigned long stixxxx_pinconf_delay_to_bit(unsigned int delay,
+ const struct stixxxx_retime_params *rt_params,
+ unsigned long config)
+{
+ unsigned int *delay_times;
+ int num_delay_times, i, closest_index = -1;
+ unsigned int closest_divergence = UINT_MAX;
+
+ if (STIXXXX_PINCONF_UNPACK_OE(config)) {
+ delay_times = rt_params->delay_times_out;
+ num_delay_times = rt_params->num_delay_times_out;
+ } else {
+ delay_times = rt_params->delay_times_in;
+ num_delay_times = rt_params->num_delay_times_in;
+ }
+
+ for (i = 0; i < num_delay_times; i++) {
+ unsigned int divergence = abs(delay - delay_times[i]);
+
+ if (divergence == 0)
+ return i;
+
+ if (divergence < closest_divergence) {
+ closest_divergence = divergence;
+ closest_index = i;
+ }
+ }
+
+ pr_warn("Attempt to set delay %d, closest available %d\n",
+ delay, delay_times[closest_index]);
+
+ return closest_index;
+}
+
+static unsigned long stixxxx_pinconf_bit_to_delay(unsigned int index,
+ const struct stixxxx_retime_params *rt_params,
+ unsigned long output)
+{
+ unsigned int *delay_times;
+ int num_delay_times;
+
+ if (output) {
+ delay_times = rt_params->delay_times_out;
+ num_delay_times = rt_params->num_delay_times_out;
+ } else {
+ delay_times = rt_params->delay_times_in;
+ num_delay_times = rt_params->num_delay_times_in;
+ }
+
+ if (index < num_delay_times) {
+ return delay_times[index];
+ } else {
+ pr_warn("Delay not found in/out delay list\n");
+ return 0;
+ }
+}
+
+static void stixxxx_pinconf_set_retime_packed(
+ struct stixxxx_pio_control *pc,
+ unsigned long config, int pin)
+{
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+ struct regmap_field **regs;
+ unsigned int values[2];
+ unsigned long mask;
+ int i, j;
+ int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+ int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+ int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+ int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+ int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+ unsigned long delay = stixxxx_pinconf_delay_to_bit(
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+ pc->rt_params, config);
+
+ unsigned long rt_cfg =
+ ((clk & 1) << offset->clk1notclk0_offset) |
+ ((clknotdata & 1) << offset->clknotdata_offset) |
+ ((delay & 1) << offset->delay_lsb_offset) |
+ (((delay >> 1) & 1) << offset->delay_msb_offset) |
+ ((double_edge & 1) << offset->double_edge_offset) |
+ ((invertclk & 1) << offset->invertclk_offset) |
+ ((retime & 1) << offset->retime_offset);
+
+ regs = pc->retiming;
+ regmap_field_read(regs[0], &values[0]);
+ regmap_field_read(regs[1], &values[1]);
+
+ for (i = 0; i < 2; i++) {
+ mask = BIT(pin);
+ for (j = 0; j < 4; j++) {
+ if (rt_cfg & 1)
+ values[i] |= mask;
+ else
+ values[i] &= ~mask;
+ mask <<= 8;
+ rt_cfg >>= 1;
+ }
+ }
+
+ regmap_field_write(regs[0], values[0]);
+ regmap_field_write(regs[1], values[1]);
+}
+
+static void stixxxx_pinconf_set_retime_dedicated(
+ struct stixxxx_pio_control *pc,
+ unsigned long config, int pin)
+{
+ struct regmap_field *reg;
+ int input = STIXXXX_PINCONF_UNPACK_OE(config) ? 0 : 1;
+ int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+ int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+ int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+ int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+ int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+ unsigned long delay = stixxxx_pinconf_delay_to_bit(
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+ pc->rt_params, config);
+
+ unsigned long retime_config =
+ ((clk & 0x3) << 0) |
+ ((clknotdata & 0x1) << 2) |
+ ((delay & 0xf) << 3) |
+ ((input & 0x1) << 7) |
+ ((double_edge & 0x1) << 8) |
+ ((invertclk & 0x1) << 9) |
+ ((retime & 0x1) << 10);
+
+ reg = pc->retiming[pin];
+ regmap_field_write(reg, retime_config);
+}
+
+static void stixxxx_pinconf_get_direction(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long *config)
+{
+ unsigned int oe_value, pu_value, od_value;
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ regmap_field_read(pc->oe, &oe_value);
+ regmap_field_read(pc->pu, &pu_value);
+ regmap_field_read(pc->od, &od_value);
+
+ oe_value = (oe_value >> pin) & 1;
+ pu_value = (pu_value >> pin) & 1;
+ od_value = (od_value >> pin) & 1;
+
+ STIXXXX_PINCONF_PACK_OE(*config, oe_value);
+ STIXXXX_PINCONF_PACK_PU(*config, pu_value);
+ STIXXXX_PINCONF_PACK_OD(*config, od_value);
+}
+
+static int stixxxx_pinconf_get_retime_packed(
+ struct stixxxx_pio_control *pc,
+ int pin, unsigned long *config)
+{
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+ unsigned long delay_bits, delay, rt_reduced;
+ unsigned int rt_value[2];
+ int i, j;
+ int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+ regmap_field_read(pc->retiming[0], &rt_value[0]);
+ regmap_field_read(pc->retiming[1], &rt_value[1]);
+
+ rt_reduced = 0;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 4; j++) {
+ if (rt_value[i] & (1<<((8*j)+pin)))
+ rt_reduced |= 1 << ((i*4)+j);
+ }
+ }
+
+ STIXXXX_PINCONF_PACK_RT(*config,
+ (rt_reduced >> offset->retime_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_CLK(*config,
+ (rt_reduced >> offset->clk1notclk0_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config,
+ (rt_reduced >> offset->clknotdata_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config,
+ (rt_reduced >> offset->double_edge_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config,
+ (rt_reduced >> offset->invertclk_offset) & 1);
+
+ delay_bits = (((rt_reduced >> offset->delay_msb_offset) & 1)<<1) |
+ ((rt_reduced >> offset->delay_lsb_offset) & 1);
+ delay = stixxxx_pinconf_bit_to_delay(delay_bits, rt_params, output);
+ STIXXXX_PINCONF_PACK_RT_DELAY(*config, delay);
+ return 0;
+}
+
+static int stixxxx_pinconf_get_retime_dedicated(
+ struct stixxxx_pio_control *pc,
+ int pin, unsigned long *config)
+{
+ unsigned int value;
+ unsigned long delay_bits, delay;
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+ regmap_field_read(pc->retiming[pin], &value);
+ STIXXXX_PINCONF_PACK_RT_CLK(*config, ((value >> 0) & 0x3));
+ STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config, ((value >> 2) & 0x1));
+ delay_bits = ((value >> 3) & 0xf);
+ delay = stixxxx_pinconf_bit_to_delay(delay_bits, rt_params, output);
+ STIXXXX_PINCONF_PACK_RT_DELAY(*config, delay);
+ STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config, ((value >> 8) & 0x1));
+ STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config, ((value >> 9) & 0x1));
+ STIXXXX_PINCONF_PACK_RT(*config, ((value >> 10) & 0x1));
+
+ return 0;
+}
+
+/* GPIO related functions */
+
+static inline void __stixxxx_gpio_set(struct stixxxx_gpio_port *port,
+ unsigned offset, int value)
+{
+ if (value)
+ writel(BIT(offset), port->base + REG_PIO_SET_POUT);
+ else
+ writel(BIT(offset), port->base + REG_PIO_CLR_POUT);
+}
+
+static void stixxxx_gpio_direction(unsigned int gpio, unsigned int direction)
+{
+ int port_num = stixxxx_gpio_port(gpio);
+ int offset = stixxxx_gpio_pin(gpio);
+ struct stixxxx_gpio_port *port = gpio_ports[port_num];
+ int i = 0;
+
+ for (i = 0; i <= 2; i++) {
+ if (direction & BIT(i))
+ writel(BIT(offset), port->base + REG_PIO_SET_PC(i));
+ else
+ writel(BIT(offset), port->base + REG_PIO_CLR_PC(i));
+ }
+}
+
+static int stixxxx_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void stixxxx_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+
+static int stixxxx_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+
+ return (readl(port->base + REG_PIO_PIN) >> offset) & 1;
+}
+
+static void stixxxx_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+ __stixxxx_gpio_set(port, offset, value);
+}
+
+static int stixxxx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_gpio_direction_input(chip->base + offset);
+ return 0;
+}
+
+static int stixxxx_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+
+ __stixxxx_gpio_set(port, offset, value);
+ pinctrl_gpio_direction_output(chip->base + offset);
+
+ return 0;
+}
+
+static int stixxxx_gpio_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec, u32 *flags)
+{
+ if (WARN_ON(gc->of_gpio_n_cells < 1))
+ return -EINVAL;
+
+ if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
+ return -EINVAL;
+
+ if (gpiospec->args[0] > gc->ngpio)
+ return -EINVAL;
+
+ return gpiospec->args[0];
+}
+
+/* Pinctrl Groups */
+static int stixxxx_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->ngroups;
+}
+
+static const char *stixxxx_pctl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->groups[selector].name;
+}
+
+static int stixxxx_pctl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned selector, const unsigned **pins, unsigned *npins)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ if (selector >= info->ngroups)
+ return -EINVAL;
+
+ *pins = info->groups[selector].pins;
+ *npins = info->groups[selector].npins;
+
+ return 0;
+}
+
+static const inline struct stixxxx_pctl_group *stixxxx_pctl_find_group_by_name(
+ const struct stixxxx_pinctrl *info, const char *name)
+{
+ int i;
+
+ for (i = 0; i < info->ngroups; i++) {
+ if (!strcmp(info->groups[i].name, name))
+ return &info->groups[i];
+ }
+
+ return NULL;
+}
+
+static int stixxxx_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np, struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ const struct stixxxx_pctl_group *grp;
+ struct pinctrl_map *new_map;
+ struct device_node *parent;
+ int map_num, i;
+
+ grp = stixxxx_pctl_find_group_by_name(info, np->name);
+ if (!grp) {
+ dev_err(info->dev, "unable to find group for node %s\n",
+ np->name);
+ return -EINVAL;
+ }
+
+ map_num = grp->npins + 1;
+ new_map = devm_kzalloc(pctldev->dev,
+ sizeof(*new_map) * map_num, GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+
+ parent = of_get_parent(np);
+ if (!parent) {
+ devm_kfree(pctldev->dev, new_map);
+ return -EINVAL;
+ }
+
+ *map = new_map;
+ *num_maps = map_num;
+ new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+ new_map[0].data.mux.function = parent->name;
+ new_map[0].data.mux.group = np->name;
+ of_node_put(parent);
+
+ /* create config map per pin */
+ new_map++;
+ for (i = 0; i < grp->npins; i++) {
+ new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+ new_map[i].data.configs.group_or_pin =
+ pin_get_name(pctldev, grp->pins[i]);
+ new_map[i].data.configs.configs = &grp->pin_conf[i].config;
+ new_map[i].data.configs.num_configs = 1;
+ }
+ dev_info(pctldev->dev, "maps: function %s group %s num %d\n",
+ (*map)->data.mux.function, grp->name, map_num);
+
+ return 0;
+}
+
+static void stixxxx_pctl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static struct pinctrl_ops stixxxx_pctlops = {
+ .get_groups_count = stixxxx_pctl_get_groups_count,
+ .get_group_pins = stixxxx_pctl_get_group_pins,
+ .get_group_name = stixxxx_pctl_get_group_name,
+ .dt_node_to_map = stixxxx_pctl_dt_node_to_map,
+ .dt_free_map = stixxxx_pctl_dt_free_map,
+};
+
+/* Pinmux */
+static int stixxxx_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->nfunctions;
+}
+
+const char *stixxxx_pmx_get_fname(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->functions[selector].name;
+}
+
+static int stixxxx_pmx_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector, const char * const **grps, unsigned * const ngrps)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ *grps = info->functions[selector].groups;
+ *ngrps = info->functions[selector].ngroups;
+
+ return 0;
+}
+
+static struct stixxxx_pio_control *stixxxx_get_pio_control(
+ struct stixxxx_pinctrl *info, int pin_id)
+{
+ int index = stixxxx_gpio_port(pin_id) - info->gpio_ranges[0]->id;
+ return &info->pio_controls[index];
+}
+
+static int stixxxx_pmx_enable(struct pinctrl_dev *pctldev, unsigned fselector,
+ unsigned group)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct stixxxx_pinconf *conf = info->groups[group].pin_conf;
+ struct stixxxx_pio_control *pc;
+ int i;
+
+ for (i = 0; i < info->groups[group].npins; i++) {
+ pc = stixxxx_get_pio_control(info, conf[i].pin);
+ stixxxx_pctl_set_function(pc, conf[i].pin,
+ info->groups[group].altfunc);
+ }
+
+ return 0;
+}
+
+static void stixxxx_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+}
+
+static int stixxxx_pmx_set_gpio_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned gpio,
+ bool input)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ int offset = range->id - info->gpio_ranges[0]->id;
+ struct stixxxx_pio_control *pc = &info->pio_controls[offset];
+ /*
+ * When a PIO port is used in its primary function mode (altfunc = 0)
+ * Output Enable (OE), Open Drain(OD), and Pull Up (PU)
+ * for the primary PIO functions are driven by the related PIO block
+ */
+ stixxxx_pctl_set_function(pc, gpio, 0);
+ stixxxx_gpio_direction(gpio, input ?
+ STIXXXX_GPIO_DIRECTION_IN : STIXXXX_GPIO_DIRECTION_OUT);
+
+ return 0;
+}
+
+static struct pinmux_ops stixxxx_pmxops = {
+ .get_functions_count = stixxxx_pmx_get_funcs_count,
+ .get_function_name = stixxxx_pmx_get_fname,
+ .get_function_groups = stixxxx_pmx_get_groups,
+ .enable = stixxxx_pmx_enable,
+ .disable = stixxxx_pmx_disable,
+ .gpio_set_direction = stixxxx_pmx_set_gpio_direction,
+};
+
+/* Pinconf */
+static void stixxxx_pinconf_get_retime(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long *config)
+{
+ int pin = stixxxx_gpio_pin(pin_id);
+ if (pc->rt_style == stixxxx_retime_style_packed)
+ stixxxx_pinconf_get_retime_packed(pc, pin, config);
+ else if (pc->rt_style == stixxxx_retime_style_dedicated)
+ if ((BIT(pin) & pc->rt_pin_mask))
+ stixxxx_pinconf_get_retime_dedicated(pc, pin, config);
+}
+
+static void stixxxx_pinconf_set_retime(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long config)
+{
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ if (pc->rt_style == stixxxx_retime_style_packed)
+ stixxxx_pinconf_set_retime_packed(pc, config, pin);
+ else if (pc->rt_style == stixxxx_retime_style_dedicated)
+ if ((BIT(pin) & pc->rt_pin_mask))
+ stixxxx_pinconf_set_retime_dedicated(pc, config, pin);
+}
+
+static int stixxxx_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long config)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct stixxxx_pio_control *pc = stixxxx_get_pio_control(info, pin_id);
+
+ stixxxx_pinconf_set_direction(pc, pin_id, config);
+ stixxxx_pinconf_set_retime(pc, pin_id, config);
+ return 0;
+}
+
+static int stixxxx_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long *config)
+{
+ struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ struct stixxxx_pio_control *pc = stixxxx_get_pio_control(info, pin_id);
+
+ *config = 0;
+ stixxxx_pinconf_get_direction(pc, pin_id, config);
+ stixxxx_pinconf_get_retime(pc, pin_id, config);
+
+ return 0;
+}
+
+static void stixxxx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin_id)
+{
+ unsigned long config;
+ stixxxx_pinconf_get(pctldev, pin_id, &config);
+
+ seq_printf(s, "[OE:%ld,PU:%ld,OD:%ld]\n"
+ "\t\t[retime:%ld,invclk:%ld,clknotdat:%ld,"
+ "de:%ld,rt-clk:%ld,rt-delay:%ld]",
+ STIXXXX_PINCONF_UNPACK_OE(config),
+ STIXXXX_PINCONF_UNPACK_PU(config),
+ STIXXXX_PINCONF_UNPACK_OD(config),
+ STIXXXX_PINCONF_UNPACK_RT(config),
+ STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config),
+ STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config),
+ STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config),
+ STIXXXX_PINCONF_UNPACK_RT_CLK(config),
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config));
+}
+
+static struct pinconf_ops stixxxx_confops = {
+ .pin_config_get = stixxxx_pinconf_get,
+ .pin_config_set = stixxxx_pinconf_set,
+ .pin_config_dbg_show = stixxxx_pinconf_dbg_show,
+};
+
+static int stixxxx_pinconf_dt_parse_rt_params(struct stixxxx_pinctrl *info,
+ struct device_node *np, struct stixxxx_retime_params *params)
+{
+ struct stixxxx_retime_offset *rt_offset;
+ int delay_count = 0;
+ int len;
+ if (of_find_property(np, "st,retime-in-delay", &len))
+ delay_count = len/sizeof(__be32);
+ else
+ dev_err(info->dev, "No delays found\n");
+
+ params->num_delay_times_out = delay_count;
+ params->num_delay_times_in = delay_count;
+ params->delay_times_in = devm_kzalloc(info->dev,
+ sizeof(u32) * delay_count, GFP_KERNEL);
+ params->delay_times_out = devm_kzalloc(info->dev,
+ sizeof(u32) * delay_count, GFP_KERNEL);
+
+ if (!params->delay_times_in || !params->delay_times_out)
+ return -ENOMEM;
+
+ of_property_read_u32_array(np, "st,retime-in-delay",
+ (u32 *)params->delay_times_in, delay_count);
+ of_property_read_u32_array(np, "st,retime-out-delay",
+ (u32 *)params->delay_times_out, delay_count);
+
+ if (of_device_is_compatible(np, "st,stih415-pinctrl")) {
+ rt_offset = devm_kzalloc(info->dev,
+ sizeof(*rt_offset), GFP_KERNEL);
+
+ if (!rt_offset)
+ return -ENOMEM;
+
+ rt_offset->clk1notclk0_offset = 0;
+ rt_offset->delay_lsb_offset = 2;
+ rt_offset->delay_msb_offset = 3;
+ rt_offset->invertclk_offset = 4;
+ rt_offset->retime_offset = 5;
+ rt_offset->clknotdata_offset = 6;
+ rt_offset->double_edge_offset = 7;
+ params->retime_offset = rt_offset;
+ }
+
+ return 0;
+}
+
+static const char *gpio_compat = "st,stixxxx-gpio";
+
+static void stixxxx_pctl_dt_child_count(struct stixxxx_pinctrl *info,
+ struct device_node *np)
+{
+ struct device_node *child;
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ info->nbanks++;
+ } else {
+ info->nfunctions++;
+ info->ngroups += of_get_child_count(child);
+ }
+ }
+}
+
+static int stixxxx_pctl_dt_get_retime_conf(struct stixxxx_pinctrl *info,
+ struct stixxxx_pio_control *pc, u32 *syscfg)
+{
+ unsigned int j;
+ int rt_syscfg = *syscfg;
+ struct device_node *np = info->dev->of_node;
+
+ if (of_device_is_compatible(np, "st,stih415-pinctrl")) {
+ pc->rt_style = stixxxx_retime_style_packed;
+ for (j = 0; j < 2; j++) {
+ struct reg_field rt_reg =
+ REG_FIELD(4 * rt_syscfg ++, 0, 31);
+ pc->retiming[j] = devm_regmap_field_alloc(info->dev,
+ info->regmap, rt_reg);
+ if (IS_ERR(pc->retiming[j]))
+ return -ENODATA;
+ }
+ } else if (of_device_is_compatible(np, "st,stih416-pinctrl")) {
+ pc->rt_style = stixxxx_retime_style_dedicated;
+ for (j = 0; j < 8; j++) {
+ if ((1<<j) & pc->rt_pin_mask) {
+ struct reg_field rt_reg =
+ REG_FIELD(4 * rt_syscfg ++, 0, 31);
+ pc->retiming[j] = devm_regmap_field_alloc(
+ info->dev, info->regmap, rt_reg);
+ if (IS_ERR(pc->retiming[j]))
+ return -ENODATA;
+ }
+ }
+ } else {
+ pc->rt_style = stixxxx_retime_style_none;
+ }
+
+ *syscfg = rt_syscfg;
+ return 0;
+}
+
+static int stixxxx_pctl_dt_init(struct stixxxx_pinctrl *info,
+ struct device_node *np)
+{
+ struct stixxxx_pio_control *pc;
+ struct stixxxx_retime_params *rt_params;
+ struct device *dev = info->dev;
+ struct regmap *regmap;
+ unsigned int i = 0;
+ struct device_node *child = NULL;
+ u32 alt_syscfg, oe_syscfg, pu_syscfg, od_syscfg, rt_syscfg;
+ u32 syscfg_offsets[5];
+ u32 msb, lsb;
+
+ pc = devm_kzalloc(dev, sizeof(*pc) * info->nbanks, GFP_KERNEL);
+ rt_params = devm_kzalloc(dev, sizeof(*rt_params), GFP_KERNEL);
+
+ if (!pc || !rt_params)
+ return -ENOMEM;
+
+ regmap = syscfg_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (!regmap) {
+ dev_err(dev, "No syscfg phandle specified\n");
+ return -ENOMEM;
+ }
+ info->regmap = regmap;
+ info->pio_controls = pc;
+ if (stixxxx_pinconf_dt_parse_rt_params(info, np, rt_params))
+ return -ENOMEM;
+
+ if (of_property_read_u32_array(np, "st,syscfg-offsets",
+ syscfg_offsets, 5)) {
+ dev_err(dev, "Syscfg offsets not found\n");
+ return -EINVAL;
+ }
+ alt_syscfg = syscfg_offsets[0];
+ oe_syscfg = syscfg_offsets[1];
+ pu_syscfg = syscfg_offsets[2];
+ od_syscfg = syscfg_offsets[3];
+ rt_syscfg = syscfg_offsets[4];
+
+ lsb = 0;
+ msb = 7;
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ struct reg_field alt_reg =
+ REG_FIELD(4 * alt_syscfg++, 0, 31);
+ struct reg_field oe_reg =
+ REG_FIELD(4 * oe_syscfg, lsb, msb);
+ struct reg_field pu_reg =
+ REG_FIELD(4 * pu_syscfg, lsb, msb);
+ struct reg_field od_reg =
+ REG_FIELD(4 * od_syscfg, lsb, msb);
+ pc[i].rt_params = rt_params;
+
+ pc[i].alt = devm_regmap_field_alloc(dev,
+ regmap, alt_reg);
+ pc[i].oe = devm_regmap_field_alloc(dev,
+ regmap, oe_reg);
+ pc[i].pu = devm_regmap_field_alloc(dev,
+ regmap, pu_reg);
+ pc[i].od = devm_regmap_field_alloc(dev,
+ regmap, od_reg);
+
+ if (IS_ERR(pc[i].alt) || IS_ERR(pc[i].oe)
+ || IS_ERR(pc[i].pu) || IS_ERR(pc[i].od))
+ goto failed;
+
+ of_property_read_u32(child, "st,retime-pin-mask",
+ &pc[i].rt_pin_mask);
+
+ stixxxx_pctl_dt_get_retime_conf(info, &pc[i],
+ &rt_syscfg);
+ i++;
+ if (msb == 31) {
+ oe_syscfg++;
+ pu_syscfg++;
+ od_syscfg++;
+ lsb = 0;
+ msb = 7;
+ } else {
+ lsb += 8;
+ msb += 8;
+ }
+ }
+ }
+
+ return 0;
+failed:
+ dev_err(dev, "Unable to allocate syscfgs\n");
+ return -ENOMEM;
+}
+
+#define OF_GPIO_ARGS_MIN (3)
+/*
+ * Each pin is represented in of the below forms.
+ * <bank offset direction func rt_type rt_delay rt_clk>
+ */
+static int stixxxx_pctl_dt_parse_groups(struct device_node *np,
+ struct stixxxx_pctl_group *grp, struct stixxxx_pinctrl *info, int idx)
+{
+ /* bank pad direction val altfunction */
+ const __be32 *list;
+ struct property *pp;
+ struct stixxxx_pinconf *conf;
+ phandle phandle;
+ struct device_node *pins;
+ u32 pin;
+ int i = 0, npins = 0, nr_props;
+
+ pins = of_get_child_by_name(np, "st,pins");
+ if (!pins)
+ return -ENODATA;
+
+ for_each_property_of_node(pins, pp) {
+ /* Skip those we do not want to proceed */
+ if (!strcmp(pp->name, "name"))
+ continue;
+
+ if (pp && (pp->length/sizeof(__be32)) >= OF_GPIO_ARGS_MIN) {
+ npins++;
+ } else {
+ pr_warn("Invalid st,pins in %s node\n", np->name);
+ return -EINVAL;
+ }
+ }
+
+ grp->npins = npins;
+ grp->name = np->name;
+ grp->pins = devm_kzalloc(info->dev, npins * sizeof(u32), GFP_KERNEL);
+ grp->pin_conf = devm_kzalloc(info->dev,
+ npins * sizeof(*conf), GFP_KERNEL);
+ of_property_read_u32(np, "st,function", &grp->altfunc);
+
+ if (!grp->pins || !grp->pin_conf)
+ return -ENOMEM;
+
+ /* <bank offset direction rt_type rt_delay rt_clk> */
+ for_each_property_of_node(pins, pp) {
+ if (!strcmp(pp->name, "name"))
+ continue;
+ nr_props = pp->length/sizeof(u32);
+ list = pp->value;
+ conf = &grp->pin_conf[i];
+
+ /* bank & offset */
+ phandle = be32_to_cpup(list++);
+ pin = be32_to_cpup(list++);
+ conf->pin = of_get_named_gpio(pins, pp->name, 0);
+ conf->name = pp->name;
+ grp->pins[i] = conf->pin;
+
+ conf->config = 0;
+ /* direction */
+ conf->config |= be32_to_cpup(list++);
+ /* rt_type rt_delay rt_clk */
+ if (nr_props >= OF_GPIO_ARGS_MIN + 2) {
+ /* rt_type */
+ conf->config |= be32_to_cpup(list++);
+ /* rt_delay */
+ conf->config |= be32_to_cpup(list++);
+ /* rt_clk */
+ if (nr_props > OF_GPIO_ARGS_MIN + 2)
+ conf->config |= be32_to_cpup(list++);
+ }
+ i++;
+ }
+ of_node_put(pins);
+
+ return 0;
+}
+
+static int stixxxx_pctl_parse_functions(struct device_node *np,
+ struct stixxxx_pinctrl *info, u32 index, int *grp_index)
+{
+ struct device_node *child;
+ struct stixxxx_pmx_func *func;
+ struct stixxxx_pctl_group *grp;
+ int ret, i;
+
+ func = &info->functions[index];
+ func->name = np->name;
+ func->ngroups = of_get_child_count(np);
+ if (func->ngroups <= 0) {
+ dev_err(info->dev, "No groups defined\n");
+ return -EINVAL;
+ }
+ func->groups = devm_kzalloc(info->dev,
+ func->ngroups * sizeof(char *), GFP_KERNEL);
+ if (!func->groups)
+ return -ENOMEM;
+
+ i = 0;
+ for_each_child_of_node(np, child) {
+ func->groups[i] = child->name;
+ grp = &info->groups[*grp_index];
+ *grp_index += 1;
+ ret = stixxxx_pctl_dt_parse_groups(child, grp, info, i++);
+ if (ret)
+ return ret;
+ }
+ dev_info(info->dev, "Function[%d\t name:%s,\tgroups:%d]\n",
+ index, func->name, func->ngroups);
+
+ return 0;
+}
+
+static struct pinctrl_gpio_range *find_gpio_range(struct device_node *np)
+{
+ int i;
+ for (i = 0; i < STIXXXX_MAX_GPIO_BANKS; i++)
+ if (gpio_ports[i]->of_node == np)
+ return &gpio_ports[i]->range;
+
+ return NULL;
+}
+
+static int stixxxx_pctl_probe_dt(struct platform_device *pdev,
+ struct pinctrl_desc *pctl_desc, struct stixxxx_pinctrl *info)
+{
+ int ret = 0;
+ int i = 0, j = 0, k = 0, bank;
+ struct pinctrl_pin_desc *pdesc;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child;
+ int grp_index = 0;
+
+ stixxxx_pctl_dt_child_count(info, np);
+ if (info->nbanks < 1) {
+ dev_err(&pdev->dev, "you need atleast one gpio bank\n");
+ return -EINVAL;
+ }
+
+ ret = stixxxx_pctl_dt_init(info, np);
+ if (ret)
+ return ret;
+
+ dev_info(&pdev->dev, "nbanks = %d\n", info->nbanks);
+ dev_info(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+ dev_info(&pdev->dev, "ngroups = %d\n", info->ngroups);
+ info->functions = devm_kzalloc(&pdev->dev,
+ info->nfunctions * sizeof(*info->functions), GFP_KERNEL);
+
+ info->groups = devm_kzalloc(&pdev->dev,
+ info->ngroups * sizeof(*info->groups) , GFP_KERNEL);
+
+ info->gpio_ranges = devm_kzalloc(&pdev->dev,
+ info->nbanks * sizeof(*info->gpio_ranges), GFP_KERNEL);
+
+ if (!info->functions || !info->groups)
+ return -ENOMEM;
+
+ pctl_desc->npins = info->nbanks * STIXXXX_GPIO_PINS_PER_PORT;
+ pdesc = devm_kzalloc(&pdev->dev,
+ sizeof(*pdesc) * pctl_desc->npins, GFP_KERNEL);
+ if (!pdesc)
+ return -ENOMEM;
+
+ pctl_desc->pins = pdesc;
+
+ bank = 0;
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ info->gpio_ranges[bank] = find_gpio_range(child);
+ k = info->gpio_ranges[bank]->pin_base;
+ for (j = 0; j < STIXXXX_GPIO_PINS_PER_PORT; j++, k++) {
+ const char *port_name = NULL;
+ pdesc->number = k;
+ of_property_read_string(child, "st,bank-name",
+ &port_name);
+ pdesc->name = kasprintf(GFP_KERNEL, "%s[%d]",
+ port_name ? : "PIO",
+ port_name ? j : k);
+ pdesc++;
+ }
+ bank++;
+ } else {
+ ret = stixxxx_pctl_parse_functions(child, info,
+ i++, &grp_index);
+ if (ret) {
+ dev_err(&pdev->dev, "No functions found.\n");
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int stixxxx_pctl_probe(struct platform_device *pdev)
+{
+ struct stixxxx_pinctrl *info;
+ struct pinctrl_desc *pctl_desc;
+ int ret, i;
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "device node not found.\n");
+ return -EINVAL;
+ }
+
+ pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
+ if (!pctl_desc)
+ return -ENOMEM;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = &pdev->dev;
+ platform_set_drvdata(pdev, info);
+ ret = stixxxx_pctl_probe_dt(pdev, pctl_desc, info);
+ if (ret)
+ return ret;
+
+ pctl_desc->owner = THIS_MODULE,
+ pctl_desc->pctlops = &stixxxx_pctlops,
+ pctl_desc->pmxops = &stixxxx_pmxops,
+ pctl_desc->confops = &stixxxx_confops,
+ pctl_desc->name = dev_name(&pdev->dev);
+
+ info->pctl = pinctrl_register(pctl_desc, &pdev->dev, info);
+ if (IS_ERR(info->pctl)) {
+ dev_err(&pdev->dev, "Failed pinctrl registration\n");
+ return PTR_ERR(info->pctl);
+ }
+
+ for (i = 0; i < info->nbanks; i++)
+ pinctrl_add_gpio_range(info->pctl, info->gpio_ranges[i]);
+
+ return 0;
+}
+
+static struct gpio_chip stixxxx_gpio_template = {
+ .request = stixxxx_gpio_request,
+ .free = stixxxx_gpio_free,
+ .get = stixxxx_gpio_get,
+ .set = stixxxx_gpio_set,
+ .direction_input = stixxxx_gpio_direction_input,
+ .direction_output = stixxxx_gpio_direction_output,
+ .ngpio = STIXXXX_GPIO_PINS_PER_PORT,
+ .of_gpio_n_cells = 1,
+ .of_xlate = stixxxx_gpio_xlate,
+};
+
+static int stixxxx_gpio_probe(struct platform_device *pdev)
+{
+ struct stixxxx_gpio_port *port;
+ struct pinctrl_gpio_range *range;
+ struct device_node *np = pdev->dev.of_node;
+ int port_num = of_alias_get_id(np, "gpio");
+ struct resource *res;
+ int err;
+
+ port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ port->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!port->base) {
+ dev_err(&pdev->dev, "Can't get IO memory mapping!\n");
+ return -ENODEV;
+ }
+
+ of_property_read_string(np, "st,bank-name", &port->bank_name);
+ port->of_node = np;
+
+ port->gpio_chip = stixxxx_gpio_template;
+ port->gpio_chip.base = port_num * STIXXXX_GPIO_PINS_PER_PORT;
+ port->gpio_chip.ngpio = STIXXXX_GPIO_PINS_PER_PORT;
+ port->gpio_chip.of_node = np;
+ port->gpio_chip.label = dev_name(&pdev->dev);
+
+ dev_set_drvdata(&pdev->dev, port);
+ range = &port->range;
+ range->name = port->gpio_chip.label;
+ range->id = port_num;
+ range->pin_base = range->base = range->id * STIXXXX_GPIO_PINS_PER_PORT;
+ range->npins = port->gpio_chip.ngpio;
+ range->gc = &port->gpio_chip;
+ gpio_ports[port_num] = port;
+ err = gpiochip_add(&port->gpio_chip);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to add gpiochip(%d)!\n", port_num);
+ return err;
+ }
+ dev_info(&pdev->dev, "gpioport[%s] Added as bank%d\n",
+ port->bank_name, port_num);
+ return 0;
+}
+
+static struct of_device_id stixxxx_gpio_of_match[] = {
+ { .compatible = "st,stixxxx-gpio", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_gpio_driver = {
+ .driver = {
+ .name = "st-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stixxxx_gpio_of_match),
+ },
+ .probe = stixxxx_gpio_probe,
+};
+
+static struct of_device_id stixxxx_pctl_of_match[] = {
+ { .compatible = "st,stixxxx-pinctrl",},
+ { .compatible = "st,stih415-pinctrl",},
+ { .compatible = "st,stih416-pinctrl",},
+ { /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_pctl_driver = {
+ .driver = {
+ .name = "st-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stixxxx_pctl_of_match),
+ },
+ .probe = stixxxx_pctl_probe,
+};
+
+static int __init stixxxx_pctl_init(void)
+{
+ int ret = platform_driver_register(&stixxxx_gpio_driver);
+ if (ret)
+ return ret;
+ return platform_driver_register(&stixxxx_pctl_driver);
+}
+arch_initcall(stixxxx_pctl_init);
diff --git a/drivers/pinctrl/pinctrl-stixxxx.h b/drivers/pinctrl/pinctrl-stixxxx.h
new file mode 100644
index 0000000..e88ab09
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-stixxxx.h
@@ -0,0 +1,197 @@
+
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Authors:
+ * Srinivas Kandagatla <***@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+#define __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+
+enum stixxxx_retime_style {
+ stixxxx_retime_style_none,
+ stixxxx_retime_style_packed,
+ stixxxx_retime_style_dedicated,
+};
+
+/* Byte positions in 2 syscon words, starts from 0 */
+struct stixxxx_retime_offset {
+ int retime_offset;
+ int clk1notclk0_offset;
+ int clknotdata_offset;
+ int double_edge_offset;
+ int invertclk_offset;
+ int delay_lsb_offset;
+ int delay_msb_offset;
+};
+
+struct stixxxx_retime_params {
+ const struct stixxxx_retime_offset *retime_offset;
+ unsigned int *delay_times_in;
+ int num_delay_times_in;
+ unsigned int *delay_times_out;
+ int num_delay_times_out;
+};
+
+struct stixxxx_pio_control {
+ enum stixxxx_retime_style rt_style;
+ u32 rt_pin_mask;
+ const struct stixxxx_retime_params *rt_params;
+ struct regmap_field *alt;
+ struct regmap_field *oe, *pu, *od;
+ struct regmap_field *retiming[8];
+};
+
+/* PIO Block registers */
+/* PIO output */
+#define REG_PIO_POUT 0x00
+/* Set bits of POUT */
+#define REG_PIO_SET_POUT 0x04
+/* Clear bits of POUT */
+#define REG_PIO_CLR_POUT 0x08
+/* PIO input */
+#define REG_PIO_PIN 0x10
+/* PIO configuration */
+#define REG_PIO_PC(n) (0x20 + (n) * 0x10)
+/* Set bits of PC[2:0] */
+#define REG_PIO_SET_PC(n) (0x24 + (n) * 0x10)
+/* Clear bits of PC[2:0] */
+#define REG_PIO_CLR_PC(n) (0x28 + (n) * 0x10)
+/* PIO input comparison */
+#define REG_PIO_PCOMP 0x50
+/* Set bits of PCOMP */
+#define REG_PIO_SET_PCOMP 0x54
+/* Clear bits of PCOMP */
+#define REG_PIO_CLR_PCOMP 0x58
+/* PIO input comparison mask */
+#define REG_PIO_PMASK 0x60
+/* Set bits of PMASK */
+#define REG_PIO_SET_PMASK 0x64
+/* Clear bits of PMASK */
+#define REG_PIO_CLR_PMASK 0x68
+
+#define STIXXXX_MAX_GPIO_BANKS 32
+
+#define STIXXXX_GPIO_DIRECTION_BIDIR 0x1
+#define STIXXXX_GPIO_DIRECTION_OUT 0x2
+#define STIXXXX_GPIO_DIRECTION_IN 0x4
+
+#define STIXXXX_GPIO_PINS_PER_PORT 8
+#define stixxxx_gpio_port(gpio) ((gpio) / STIXXXX_GPIO_PINS_PER_PORT)
+#define stixxxx_gpio_pin(gpio) ((gpio) % STIXXXX_GPIO_PINS_PER_PORT)
+
+/* pinconf */
+/*
+ * Pinconf is represented in an opaque unsigned long variable.
+ * Below is the bit allocation details for each possible configuration.
+ * All the bit fields can be encapsulated into four variables
+ * (direction, retime-type, retime-clk, retime-delay)
+ *
+ * +----------------+
+ *[31:28]| reserved-3 |
+ * +----------------+-------------
+ *[27] | oe | |
+ * +----------------+ v
+ *[26] | pu | [Direction ]
+ * +----------------+ ^
+ *[25] | od | |
+ * +----------------+-------------
+ *[24] | reserved-2 |
+ * +----------------+-------------
+ *[23] | retime | |
+ * +----------------+ |
+ *[22] | retime-invclk | |
+ * +----------------+ v
+ *[21] |retime-clknotdat| [Retime-type ]
+ * +----------------+ ^
+ *[20] | retime-de | |
+ * +----------------+-------------
+ *[19:18]| retime-clk |------>[Retime-Clk ]
+ * +----------------+
+ *[17:16]| reserved-1 |
+ * +----------------+
+ *[15..0]| retime-delay |------>[Retime Delay]
+ * +----------------+
+ */
+
+#define STIXXXX_PINCONF_UNPACK(conf, param)\
+ ((conf >> STIXXXX_PINCONF_ ##param ##_SHIFT) \
+ & STIXXXX_PINCONF_ ##param ##_MASK)
+
+#define STIXXXX_PINCONF_PACK(conf, val, param) (conf |=\
+ ((val & STIXXXX_PINCONF_ ##param ##_MASK) << \
+ STIXXXX_PINCONF_ ##param ##_SHIFT))
+
+/* Output enable */
+#define STIXXXX_PINCONF_OE_MASK 0x1
+#define STIXXXX_PINCONF_OE_SHIFT 27
+#define STIXXXX_PINCONF_OE BIT(27)
+#define STIXXXX_PINCONF_UNPACK_OE(conf) STIXXXX_PINCONF_UNPACK(conf, OE)
+#define STIXXXX_PINCONF_PACK_OE(conf, val) STIXXXX_PINCONF_PACK(conf, val, OE)
+
+/* Pull Up */
+#define STIXXXX_PINCONF_PU_MASK 0x1
+#define STIXXXX_PINCONF_PU_SHIFT 26
+#define STIXXXX_PINCONF_PU BIT(26)
+#define STIXXXX_PINCONF_UNPACK_PU(conf) STIXXXX_PINCONF_UNPACK(conf, PU)
+#define STIXXXX_PINCONF_PACK_PU(conf, val) STIXXXX_PINCONF_PACK(conf, val, PU)
+
+/* Open Drain */
+#define STIXXXX_PINCONF_OD_MASK 0x1
+#define STIXXXX_PINCONF_OD_SHIFT 25
+#define STIXXXX_PINCONF_OD BIT(25)
+#define STIXXXX_PINCONF_UNPACK_OD(conf) STIXXXX_PINCONF_UNPACK(conf, OD)
+#define STIXXXX_PINCONF_PACK_OD(conf, val) STIXXXX_PINCONF_PACK(conf, val, OD)
+
+#define STIXXXX_PINCONF_RT_MASK 0x1
+#define STIXXXX_PINCONF_RT_SHIFT 23
+#define STIXXXX_PINCONF_RT BIT(23)
+#define STIXXXX_PINCONF_UNPACK_RT(conf) STIXXXX_PINCONF_UNPACK(conf, RT)
+#define STIXXXX_PINCONF_PACK_RT(conf, val) STIXXXX_PINCONF_PACK(conf, val, RT)
+
+#define STIXXXX_PINCONF_RT_INVERTCLK_MASK 0x1
+#define STIXXXX_PINCONF_RT_INVERTCLK_SHIFT 22
+#define STIXXXX_PINCONF_RT_INVERTCLK BIT(22)
+#define STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_INVERTCLK)
+#define STIXXXX_PINCONF_PACK_RT_INVERTCLK(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_INVERTCLK)
+
+#define STIXXXX_PINCONF_RT_CLKNOTDATA_MASK 0x1
+#define STIXXXX_PINCONF_RT_CLKNOTDATA_SHIFT 21
+#define STIXXXX_PINCONF_RT_CLKNOTDATA BIT(21)
+#define STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_CLKNOTDATA)
+#define STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_CLKNOTDATA)
+
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE_MASK 0x1
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE_SHIFT 20
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE BIT(20)
+#define STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_DOUBLE_EDGE)
+#define STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_DOUBLE_EDGE)
+
+#define STIXXXX_PINCONF_RT_CLK_MASK 0x3
+#define STIXXXX_PINCONF_RT_CLK_SHIFT 18
+#define STIXXXX_PINCONF_RT_CLK BIT(18)
+#define STIXXXX_PINCONF_UNPACK_RT_CLK(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_CLK)
+#define STIXXXX_PINCONF_PACK_RT_CLK(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_CLK)
+
+/* RETIME_DELAY in Pico Secs */
+#define STIXXXX_PINCONF_RT_DELAY_MASK 0xffff
+#define STIXXXX_PINCONF_RT_DELAY_SHIFT 0
+#define STIXXXX_PINCONF_UNPACK_RT_DELAY(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_DELAY)
+#define STIXXXX_PINCONF_PACK_RT_DELAY(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_DELAY)
+
+#endif /* __LINUX_DRIVERS_PINCTRL_STIXXXX_H */
--
1.7.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Linus Walleij
2013-06-16 12:17:15 UTC
Permalink
On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This pinctrl driver manages both PIO and PIO-mux block using pinctrl,
pinconf, pinmux, gpio subsystems. All the pinctrl related config
information can only come from device trees.
OK that's a good approach!
Post by Srinivas KANDAGATLA
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
@@ -0,0 +1,116 @@
+*ST pin controller.
+
+Each multi-function pin is controlled, driven and routed through the
+PIO multiplexing block. Each pin supports GPIO functionality (ALT0)
+and multiple alternate functions(ALT1 - ALTx) that directly connect
+the pin to different hardware blocks.
+
+When a pin is in GPIO mode, Output Enable (OE), Open Drain(OD), and
+Pull Up (PU) are driven by the related PIO block.
+
+ST pinctrl driver controls PIO multiplexing block and also interacts with
+gpio driver to configure a pin.
+
+Required properties: (PIO multiplexing block)
+- compatible : should be "st,stixxxx-pinctrl"
+ each subnode should set "st,stixxxx-gpio"
+ as compatible for each gpio-controller bank.
+- gpio-controller : Indicates this device is a GPIO controller
+- #gpio-cells : Should be one. The first cell is the pin number.
+- st,retime-in-delay : Should be array of delays in nsecs.
+- st,retime-out-delay : Should be array of delays in nsecs.
Please explain more verbosely what is meant by these
delays. in-delay of what? out-delay of what?
Post by Srinivas KANDAGATLA
+- st,retime-pin-mask : Should be mask to specify which pins can be retimed.
Explain what this "retimed" means.
Post by Srinivas KANDAGATLA
+- st,bank-name : Should be a name string for this bank.
Usually we only use an identifier, like a number for this, but
maybe you need this, so won't judge on it.
Post by Srinivas KANDAGATLA
+- st,syscfg : phandle of the syscfg node.
This is pretty clever.
Post by Srinivas KANDAGATLA
+- st,syscfg-offsets : Should be a 5 cell entry which represent offset of altfunc,
+ output-enable, pull-up , open drain and retime registers in the syscfg bank
No please. Use the compatible string to determine which version of the
hardware this is and encode a register offset table into the driver instead.
We do not store register offsets in the device tree, it is not a datasheet
XML container you know...

(...)
(...)
Post by Srinivas KANDAGATLA
+- st,pins : Child node with list of pins with configuration.
(...)
Post by Srinivas KANDAGATLA
+Every PIO is represented with 4-7 parameters depending on retime configuration.
+Each parameter is explained as below.
+
+-bank : Should be bank phandle to which this PIO belongs.
+-offset : Offset in the PIO bank.
+-mode :pin configuration is selected from one of the below values.
+ IN
+ IN_PU
+ OUT
+ BIDIR
+ BIDIR_PU
This looks like it could use our new generic pinconfig API.
Please follow the discussions on the mailing list and read the
latest commits to the pinctrl devel branch on this subject.

Please explain what "bidir(ectional)" actually means here:
does this mean the same as HighZ/tristate or something
else?
Post by Srinivas KANDAGATLA
+-rt_type Retiming Configuration for the pin.
+
+ ------- -------------
+ value args
+ ------- -------------
+ NICLK <delay> <clk>
+ ICLK_IO <delay> <clk>
+ BYPASS <delay>
+ DE_IO <delay> <clk>
+ SE_ICLK_IO <delay> <clk>
+ SE_NICLK_IO <delay> <clk>
+
+- delay is retime delay in pico seconds.
+ Possible values are: refer to retime-in/out-delays
Earlier it was given in nanoseconds.

And I still have no clue what "retiming" means.

I'm suspecting you cannot actually use generic pinconfig
due to all this retiming esoterica but atleast give it a thought.
Post by Srinivas KANDAGATLA
+- rt_clk :clk to be use for retime.
+ CLK_A
+ CLK_B
+ CLK_C
+ CLK_D
So this is selecting one of four available clock lines?

Should this not interact with some clk bindings for your
clock tree?
Post by Srinivas KANDAGATLA
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 8f66924..0c040a3 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -169,6 +169,17 @@ config PINCTRL_SUNXI
select PINMUX
select GENERIC_PINCONF
+config PINCTRL_STIXXXX
As mentioned elsewhere STIXXXX is a bit too much X:es in.
Please come up with some better naming if possible.
Post by Srinivas KANDAGATLA
+ bool "ST Microelectronics pin controller driver for STixxxx SoCs"
Add:
depends on OF
Post by Srinivas KANDAGATLA
+ select PINMUX
+ select PINCONF
+ help
+ Say yes here to support pinctrl interface on STixxxx SOCs.
+ This driver is used to control both PIO block and PIO-mux
+ block to configure a pin.
+
+ If unsure, say N.
(...)
Post by Srinivas KANDAGATLA
+++ b/drivers/pinctrl/pinctrl-stixxxx.c
Same naming problem. Repeat again for all identifiers in the code.
Won't mention it again.

(...)
Post by Srinivas KANDAGATLA
+#define to_stixxxx_gpio_port(chip) \
+ container_of(chip, struct stixxxx_gpio_port, gpio_chip)
+
+struct stixxxx_gpio_port {
+ struct gpio_chip gpio_chip;
+ struct pinctrl_gpio_range range;
+ void __iomem *base;
+ struct device_node *of_node;
Why do you need this? The struct gpio_chip above can contain
the of_node can it not?
Post by Srinivas KANDAGATLA
+ const char *bank_name;
+};
+static struct stixxxx_gpio_port *gpio_ports[STIXXXX_MAX_GPIO_BANKS];
This is complicating things. Can't you just store the array of GPIO ports
*inside* the struct stixxxx_pinctrl container or something?

(...)
Post by Srinivas KANDAGATLA
+/* Low level functions.. */
+static void stixxxx_pinconf_set_direction(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long config)
Why is this function called "*_set_direction" when it is also
messing with PU and OD?

_set_config would be more appropriate.

(The code looks fine.)

(...)
Post by Srinivas KANDAGATLA
+static void stixxxx_pinconf_set_retime_packed(
+ struct stixxxx_pio_control *pc,
+ unsigned long config, int pin)
+{
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+ struct regmap_field **regs;
+ unsigned int values[2];
+ unsigned long mask;
+ int i, j;
+ int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+ int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+ int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+ int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+ int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+ unsigned long delay = stixxxx_pinconf_delay_to_bit(
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+ pc->rt_params, config);
As you can see it's a bit excess of "X" above. Hard to read.
Post by Srinivas KANDAGATLA
+ unsigned long rt_cfg =
+ ((clk & 1) << offset->clk1notclk0_offset) |
+ ((clknotdata & 1) << offset->clknotdata_offset) |
+ ((delay & 1) << offset->delay_lsb_offset) |
+ (((delay >> 1) & 1) << offset->delay_msb_offset) |
+ ((double_edge & 1) << offset->double_edge_offset) |
+ ((invertclk & 1) << offset->invertclk_offset) |
+ ((retime & 1) << offset->retime_offset);
This is looking strange. Just strange.
Comments are needed I think. For example why
arey >> 1 on delay all of a sudden?

I would try to make clk, clknotdata, delay etc into bools.

Then it could be more readable like this:

#include <linux/bitops.h>

unsigned long rt_cfg = 0;

if (clk)
rt_cfg |= BIT(offset->clk1notclk0_offset);
if (clknotdata)
rt_cfg |= BIT(offset->clknotdata_offset);

etc.
Post by Srinivas KANDAGATLA
+ regs = pc->retiming;
+ regmap_field_read(regs[0], &values[0]);
+ regmap_field_read(regs[1], &values[1]);
+
+ for (i = 0; i < 2; i++) {
+ mask = BIT(pin);
+ for (j = 0; j < 4; j++) {
+ if (rt_cfg & 1)
+ values[i] |= mask;
+ else
+ values[i] &= ~mask;
+ mask <<= 8;
+ rt_cfg >>= 1;
+ }
+ }
2? 4? 8? Not quite readable with so many magic constants.
Is this "8" identical to STIXXXX_GPIO_PINS_PER_PORT?
Post by Srinivas KANDAGATLA
+ regmap_field_write(regs[0], values[0]);
+ regmap_field_write(regs[1], values[1]);
+}
(...)
Post by Srinivas KANDAGATLA
+static void stixxxx_pinconf_set_retime_dedicated(
+ struct stixxxx_pio_control *pc,
+ unsigned long config, int pin)
+{
+ struct regmap_field *reg;
+ int input = STIXXXX_PINCONF_UNPACK_OE(config) ? 0 : 1;
+ int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+ int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+ int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+ int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+ int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+ unsigned long delay = stixxxx_pinconf_delay_to_bit(
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+ pc->rt_params, config);
+
+ unsigned long retime_config =
+ ((clk & 0x3) << 0) |
+ ((clknotdata & 0x1) << 2) |
+ ((delay & 0xf) << 3) |
+ ((input & 0x1) << 7) |
+ ((double_edge & 0x1) << 8) |
+ ((invertclk & 0x1) << 9) |
+ ((retime & 0x1) << 10);
Same comments as above.

(...)
Post by Srinivas KANDAGATLA
+static void stixxxx_pinconf_get_direction(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long *config)
+{
+ unsigned int oe_value, pu_value, od_value;
+ int pin = stixxxx_gpio_pin(pin_id);
+
+ regmap_field_read(pc->oe, &oe_value);
+ regmap_field_read(pc->pu, &pu_value);
+ regmap_field_read(pc->od, &od_value);
+
+ oe_value = (oe_value >> pin) & 1;
+ pu_value = (pu_value >> pin) & 1;
+ od_value = (od_value >> pin) & 1;
+
+ STIXXXX_PINCONF_PACK_OE(*config, oe_value);
+ STIXXXX_PINCONF_PACK_PU(*config, pu_value);
+ STIXXXX_PINCONF_PACK_OD(*config, od_value);
+}
However that's quite readable actually, this part I
understand.
Post by Srinivas KANDAGATLA
+static int stixxxx_pinconf_get_retime_packed(
+ struct stixxxx_pio_control *pc,
+ int pin, unsigned long *config)
+{
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+ unsigned long delay_bits, delay, rt_reduced;
+ unsigned int rt_value[2];
+ int i, j;
+ int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+ regmap_field_read(pc->retiming[0], &rt_value[0]);
+ regmap_field_read(pc->retiming[1], &rt_value[1]);
+
+ rt_reduced = 0;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 4; j++) {
+ if (rt_value[i] & (1<<((8*j)+pin)))
+ rt_reduced |= 1 << ((i*4)+j);
+ }
+ }
Urgh 2, 4, 8??

What is happening here ... atleast a big comment
explaining the logic would be helpful. Some kind of
matrix traversal seem to be involved.
Post by Srinivas KANDAGATLA
+ STIXXXX_PINCONF_PACK_RT(*config,
+ (rt_reduced >> offset->retime_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_CLK(*config,
+ (rt_reduced >> offset->clk1notclk0_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config,
+ (rt_reduced >> offset->clknotdata_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config,
+ (rt_reduced >> offset->double_edge_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config,
+ (rt_reduced >> offset->invertclk_offset) & 1);
I would rewrite this like

if ((rt_reduced >> offset->retime_offset) & 1)
STIXXXX_PINCONF_PACK_RT(*config, 1);

See further comments on these macros below.

I prefer if they are only used to set bits to 1, then it just becomes:

if ((rt_reduced >> offset->retime_offset) & 1)
STIXXXX_PINCONF_PACK_RT(*config);

Simpler.
Post by Srinivas KANDAGATLA
+ delay_bits = (((rt_reduced >> offset->delay_msb_offset) & 1)<<1) |
+ ((rt_reduced >> offset->delay_lsb_offset) & 1);
+ delay = stixxxx_pinconf_bit_to_delay(delay_bits, rt_params, output);
+ STIXXXX_PINCONF_PACK_RT_DELAY(*config, delay);
This looks OK though.

(...)
Post by Srinivas KANDAGATLA
+static int stixxxx_pinconf_get_retime_dedicated(
+ struct stixxxx_pio_control *pc,
+ int pin, unsigned long *config)
+{
+ unsigned int value;
+ unsigned long delay_bits, delay;
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+ regmap_field_read(pc->retiming[pin], &value);
+ STIXXXX_PINCONF_PACK_RT_CLK(*config, ((value >> 0) & 0x3));
+ STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config, ((value >> 2) & 0x1));
+ delay_bits = ((value >> 3) & 0xf);
0x03? 2? 3? lots of magic constants here, can they be defined?
Post by Srinivas KANDAGATLA
+ delay = stixxxx_pinconf_bit_to_delay(delay_bits, rt_params, output);
+ STIXXXX_PINCONF_PACK_RT_DELAY(*config, delay);
+ STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config, ((value >> 8) & 0x1));
8?
Post by Srinivas KANDAGATLA
+ STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config, ((value >> 9) & 0x1));
9?
Post by Srinivas KANDAGATLA
+ STIXXXX_PINCONF_PACK_RT(*config, ((value >> 10) & 0x1));
10?

Can these be #defines?

(...)
Post by Srinivas KANDAGATLA
+static void stixxxx_gpio_direction(unsigned int gpio, unsigned int direction)
+{
+ int port_num = stixxxx_gpio_port(gpio);
+ int offset = stixxxx_gpio_pin(gpio);
+ struct stixxxx_gpio_port *port = gpio_ports[port_num];
+ int i = 0;
+
+ for (i = 0; i <= 2; i++) {
+ if (direction & BIT(i))
+ writel(BIT(offset), port->base + REG_PIO_SET_PC(i));
+ else
+ writel(BIT(offset), port->base + REG_PIO_CLR_PC(i));
+ }
Can you explain here in a comment why the loop has to hit
bits 0, 1 and 2 in this register?

(...)
Post by Srinivas KANDAGATLA
+static int stixxxx_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+
+ return (readl(port->base + REG_PIO_PIN) >> offset) & 1;
Usually we do this with the double-bang idiom:

return !!(readl(port->base + REG_PIO_PIN) & BIT(offset));
Post by Srinivas KANDAGATLA
+static void stixxxx_pctl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+}
Isn't this optional? And don't you need to free this?

(...)
Post by Srinivas KANDAGATLA
+static void stixxxx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin_id)
+{
+ unsigned long config;
+ stixxxx_pinconf_get(pctldev, pin_id, &config);
+
+ seq_printf(s, "[OE:%ld,PU:%ld,OD:%ld]\n"
+ "\t\t[retime:%ld,invclk:%ld,clknotdat:%ld,"
+ "de:%ld,rt-clk:%ld,rt-delay:%ld]",
+ STIXXXX_PINCONF_UNPACK_OE(config),
+ STIXXXX_PINCONF_UNPACK_PU(config),
+ STIXXXX_PINCONF_UNPACK_OD(config),
+ STIXXXX_PINCONF_UNPACK_RT(config),
+ STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config),
+ STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config),
+ STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config),
+ STIXXXX_PINCONF_UNPACK_RT_CLK(config),
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config));
+}
This looks real nice, but is the output human-friendly?
Well maybe the format needs to be compact like this...
Post by Srinivas KANDAGATLA
+ if (of_device_is_compatible(np, "st,stih415-pinctrl")) {
+ rt_offset = devm_kzalloc(info->dev,
+ sizeof(*rt_offset), GFP_KERNEL);
+
+ if (!rt_offset)
+ return -ENOMEM;
+
+ rt_offset->clk1notclk0_offset = 0;
+ rt_offset->delay_lsb_offset = 2;
+ rt_offset->delay_msb_offset = 3;
+ rt_offset->invertclk_offset = 4;
+ rt_offset->retime_offset = 5;
+ rt_offset->clknotdata_offset = 6;
+ rt_offset->double_edge_offset = 7;
This looks awkward and complicated.

Why not just #define these offsets and use them
directly in the code?
Post by Srinivas KANDAGATLA
+static int stixxxx_pctl_dt_init(struct stixxxx_pinctrl *info,
+ struct device_node *np)
+{
+ struct stixxxx_pio_control *pc;
+ struct stixxxx_retime_params *rt_params;
+ struct device *dev = info->dev;
+ struct regmap *regmap;
+ unsigned int i = 0;
+ struct device_node *child = NULL;
+ u32 alt_syscfg, oe_syscfg, pu_syscfg, od_syscfg, rt_syscfg;
+ u32 syscfg_offsets[5];
+ u32 msb, lsb;
+
+ pc = devm_kzalloc(dev, sizeof(*pc) * info->nbanks, GFP_KERNEL);
+ rt_params = devm_kzalloc(dev, sizeof(*rt_params), GFP_KERNEL);
+
+ if (!pc || !rt_params)
+ return -ENOMEM;
+
+ regmap = syscfg_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (!regmap) {
+ dev_err(dev, "No syscfg phandle specified\n");
+ return -ENOMEM;
+ }
+ info->regmap = regmap;
+ info->pio_controls = pc;
+ if (stixxxx_pinconf_dt_parse_rt_params(info, np, rt_params))
+ return -ENOMEM;
+
+ if (of_property_read_u32_array(np, "st,syscfg-offsets",
+ syscfg_offsets, 5)) {
+ dev_err(dev, "Syscfg offsets not found\n");
+ return -EINVAL;
+ }
+ alt_syscfg = syscfg_offsets[0];
+ oe_syscfg = syscfg_offsets[1];
+ pu_syscfg = syscfg_offsets[2];
+ od_syscfg = syscfg_offsets[3];
+ rt_syscfg = syscfg_offsets[4];
This isn't looking any fun either.

#defining the offsets avoid all this strange boilerplate.
Post by Srinivas KANDAGATLA
+ lsb = 0;
+ msb = 7;
And this.
Post by Srinivas KANDAGATLA
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ struct reg_field alt_reg =
+ REG_FIELD(4 * alt_syscfg++, 0, 31);
+ struct reg_field oe_reg =
+ REG_FIELD(4 * oe_syscfg, lsb, msb);
+ struct reg_field pu_reg =
+ REG_FIELD(4 * pu_syscfg, lsb, msb);
+ struct reg_field od_reg =
+ REG_FIELD(4 * od_syscfg, lsb, msb);
+ pc[i].rt_params = rt_params;
+
+ pc[i].alt = devm_regmap_field_alloc(dev,
+ regmap, alt_reg);
+ pc[i].oe = devm_regmap_field_alloc(dev,
+ regmap, oe_reg);
+ pc[i].pu = devm_regmap_field_alloc(dev,
+ regmap, pu_reg);
+ pc[i].od = devm_regmap_field_alloc(dev,
+ regmap, od_reg);
+
+ if (IS_ERR(pc[i].alt) || IS_ERR(pc[i].oe)
+ || IS_ERR(pc[i].pu) || IS_ERR(pc[i].od))
+ goto failed;
+
+ of_property_read_u32(child, "st,retime-pin-mask",
+ &pc[i].rt_pin_mask);
+
+ stixxxx_pctl_dt_get_retime_conf(info, &pc[i],
+ &rt_syscfg);
+ i++;
+ if (msb == 31) {
+ oe_syscfg++;
+ pu_syscfg++;
+ od_syscfg++;
+ lsb = 0;
+ msb = 7;
+ } else {
+ lsb += 8;
+ msb += 8;
+ }
Can you explain with a comment what is happening here.
Post by Srinivas KANDAGATLA
+static struct pinctrl_gpio_range *find_gpio_range(struct device_node *np)
+{
+ int i;
+ for (i = 0; i < STIXXXX_MAX_GPIO_BANKS; i++)
+ if (gpio_ports[i]->of_node == np)
+ return &gpio_ports[i]->range;
+
+ return NULL;
+}
This looks a bit like it's duplicating pinctrl_find_gpio_range_from_pin()
or similar already available from the pinctrl core. But it seems you
may need it here in this case.
Post by Srinivas KANDAGATLA
+static int stixxxx_pctl_probe(struct platform_device *pdev)
(...)
Post by Srinivas KANDAGATLA
+static int stixxxx_gpio_probe(struct platform_device *pdev)
(...)
Post by Srinivas KANDAGATLA
+static struct of_device_id stixxxx_gpio_of_match[] = {
+ { .compatible = "st,stixxxx-gpio", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_gpio_driver = {
+ .driver = {
+ .name = "st-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stixxxx_gpio_of_match),
+ },
+ .probe = stixxxx_gpio_probe,
+};
+
+static struct of_device_id stixxxx_pctl_of_match[] = {
+ { .compatible = "st,stixxxx-pinctrl",},
+ { .compatible = "st,stih415-pinctrl",},
+ { .compatible = "st,stih416-pinctrl",},
+ { /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_pctl_driver = {
+ .driver = {
+ .name = "st-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stixxxx_pctl_of_match),
+ },
+ .probe = stixxxx_pctl_probe,
+};
Why do you need separate nodes and probe functions for the
pinctrl and GPIO? Can't you just have a single pinctrl node?
Post by Srinivas KANDAGATLA
+static int __init stixxxx_pctl_init(void)
+{
+ int ret = platform_driver_register(&stixxxx_gpio_driver);
+ if (ret)
+ return ret;
+ return platform_driver_register(&stixxxx_pctl_driver);
+}
Especially since you're just registering them after each other.

Maybe you could have the GPIO nodes as children inside the
pinctrl node and iterate over with for_each_child_of_node()?

I'm not requiring you rewrite this, just that you give it a thought.

(...)
Post by Srinivas KANDAGATLA
+++ b/drivers/pinctrl/pinctrl-stixxxx.h
@@ -0,0 +1,197 @@
+
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+#define __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+
+enum stixxxx_retime_style {
+ stixxxx_retime_style_none,
+ stixxxx_retime_style_packed,
+ stixxxx_retime_style_dedicated,
+};
+
+/* Byte positions in 2 syscon words, starts from 0 */
+struct stixxxx_retime_offset {
+ int retime_offset;
+ int clk1notclk0_offset;
+ int clknotdata_offset;
+ int double_edge_offset;
+ int invertclk_offset;
+ int delay_lsb_offset;
+ int delay_msb_offset;
+};
+
+struct stixxxx_retime_params {
+ const struct stixxxx_retime_offset *retime_offset;
+ unsigned int *delay_times_in;
+ int num_delay_times_in;
+ unsigned int *delay_times_out;
+ int num_delay_times_out;
+};
+
+struct stixxxx_pio_control {
+ enum stixxxx_retime_style rt_style;
+ u32 rt_pin_mask;
+ const struct stixxxx_retime_params *rt_params;
+ struct regmap_field *alt;
+ struct regmap_field *oe, *pu, *od;
+ struct regmap_field *retiming[8];
+};
Are these used outside of the driver? If not, move it into the
driver .c file.
Post by Srinivas KANDAGATLA
+/* PIO Block registers */
+/* PIO output */
+#define REG_PIO_POUT 0x00
+/* Set bits of POUT */
+#define REG_PIO_SET_POUT 0x04
+/* Clear bits of POUT */
+#define REG_PIO_CLR_POUT 0x08
+/* PIO input */
+#define REG_PIO_PIN 0x10
+/* PIO configuration */
+#define REG_PIO_PC(n) (0x20 + (n) * 0x10)
+/* Set bits of PC[2:0] */
+#define REG_PIO_SET_PC(n) (0x24 + (n) * 0x10)
+/* Clear bits of PC[2:0] */
+#define REG_PIO_CLR_PC(n) (0x28 + (n) * 0x10)
+/* PIO input comparison */
+#define REG_PIO_PCOMP 0x50
+/* Set bits of PCOMP */
+#define REG_PIO_SET_PCOMP 0x54
+/* Clear bits of PCOMP */
+#define REG_PIO_CLR_PCOMP 0x58
+/* PIO input comparison mask */
+#define REG_PIO_PMASK 0x60
+/* Set bits of PMASK */
+#define REG_PIO_SET_PMASK 0x64
+/* Clear bits of PMASK */
+#define REG_PIO_CLR_PMASK 0x68
+
+#define STIXXXX_MAX_GPIO_BANKS 32
+
+#define STIXXXX_GPIO_DIRECTION_BIDIR 0x1
+#define STIXXXX_GPIO_DIRECTION_OUT 0x2
+#define STIXXXX_GPIO_DIRECTION_IN 0x4
+#define STIXXXX_GPIO_PINS_PER_PORT 8
Does *any* of this have to be in the header file? If not, move it
into the driver instead, so the reader don't have to shift between several
files when reading the driver code.
Post by Srinivas KANDAGATLA
+#define stixxxx_gpio_port(gpio) ((gpio) / STIXXXX_GPIO_PINS_PER_PORT)
+#define stixxxx_gpio_pin(gpio) ((gpio) % STIXXXX_GPIO_PINS_PER_PORT)
Move these three #defines into the driver and convert the
two last ones to static inlines instead. Easier to maintain.
Post by Srinivas KANDAGATLA
+
+/* pinconf */
+/*
+ * Pinconf is represented in an opaque unsigned long variable.
+ * Below is the bit allocation details for each possible configuration.
+ * All the bit fields can be encapsulated into four variables
+ * (direction, retime-type, retime-clk, retime-delay)
+ *
+ * +----------------+
+ *[31:28]| reserved-3 |
+ * +----------------+-------------
+ *[27] | oe | |
+ * +----------------+ v
+ *[26] | pu | [Direction ]
+ * +----------------+ ^
+ *[25] | od | |
+ * +----------------+-------------
+ *[24] | reserved-2 |
+ * +----------------+-------------
+ *[23] | retime | |
+ * +----------------+ |
+ *[22] | retime-invclk | |
+ * +----------------+ v
+ *[21] |retime-clknotdat| [Retime-type ]
+ * +----------------+ ^
+ *[20] | retime-de | |
+ * +----------------+-------------
+ *[19:18]| retime-clk |------>[Retime-Clk ]
+ * +----------------+
+ *[17:16]| reserved-1 |
+ * +----------------+
+ *[15..0]| retime-delay |------>[Retime Delay]
+ * +----------------+
+ */
+
+#define STIXXXX_PINCONF_UNPACK(conf, param)\
+ ((conf >> STIXXXX_PINCONF_ ##param ##_SHIFT) \
+ & STIXXXX_PINCONF_ ##param ##_MASK)
+
+#define STIXXXX_PINCONF_PACK(conf, val, param) (conf |=\
+ ((val & STIXXXX_PINCONF_ ##param ##_MASK) << \
+ STIXXXX_PINCONF_ ##param ##_SHIFT))
+
+/* Output enable */
+#define STIXXXX_PINCONF_OE_MASK 0x1
+#define STIXXXX_PINCONF_OE_SHIFT 27
+#define STIXXXX_PINCONF_OE BIT(27)
+#define STIXXXX_PINCONF_UNPACK_OE(conf) STIXXXX_PINCONF_UNPACK(conf, OE)
+#define STIXXXX_PINCONF_PACK_OE(conf, val) STIXXXX_PINCONF_PACK(conf, val, OE)
For all of these macros: why are you suppying an argument that can only
be 0 or 1?

Just alter PACK like this:

#define STIXXXX_PINCONF_PACK_OE(conf) STIXXXX_PINCONF_PACK(conf, 1, OE)

And only call it if you want to enable the feature, else avoid calling it.
There is no point of setting bits to zero with so much adoo.
Post by Srinivas KANDAGATLA
+/* Pull Up */
+#define STIXXXX_PINCONF_PU_MASK 0x1
+#define STIXXXX_PINCONF_PU_SHIFT 26
+#define STIXXXX_PINCONF_PU BIT(26)
+#define STIXXXX_PINCONF_UNPACK_PU(conf) STIXXXX_PINCONF_UNPACK(conf, PU)
+#define STIXXXX_PINCONF_PACK_PU(conf, val) STIXXXX_PINCONF_PACK(conf, val, PU)
Dito.
Post by Srinivas KANDAGATLA
+/* Open Drain */
+#define STIXXXX_PINCONF_OD_MASK 0x1
+#define STIXXXX_PINCONF_OD_SHIFT 25
+#define STIXXXX_PINCONF_OD BIT(25)
+#define STIXXXX_PINCONF_UNPACK_OD(conf) STIXXXX_PINCONF_UNPACK(conf, OD)
+#define STIXXXX_PINCONF_PACK_OD(conf, val) STIXXXX_PINCONF_PACK(conf, val, OD)
Dito.
Post by Srinivas KANDAGATLA
+#define STIXXXX_PINCONF_RT_MASK 0x1
+#define STIXXXX_PINCONF_RT_SHIFT 23
+#define STIXXXX_PINCONF_RT BIT(23)
+#define STIXXXX_PINCONF_UNPACK_RT(conf) STIXXXX_PINCONF_UNPACK(conf, RT)
+#define STIXXXX_PINCONF_PACK_RT(conf, val) STIXXXX_PINCONF_PACK(conf, val, RT)
Dito.
Post by Srinivas KANDAGATLA
+#define STIXXXX_PINCONF_RT_INVERTCLK_MASK 0x1
+#define STIXXXX_PINCONF_RT_INVERTCLK_SHIFT 22
+#define STIXXXX_PINCONF_RT_INVERTCLK BIT(22)
+#define STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_INVERTCLK)
+#define STIXXXX_PINCONF_PACK_RT_INVERTCLK(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_INVERTCLK)
Dito.
Post by Srinivas KANDAGATLA
+#define STIXXXX_PINCONF_RT_CLKNOTDATA_MASK 0x1
+#define STIXXXX_PINCONF_RT_CLKNOTDATA_SHIFT 21
+#define STIXXXX_PINCONF_RT_CLKNOTDATA BIT(21)
+#define STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_CLKNOTDATA)
+#define STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_CLKNOTDATA)
Dito.
Post by Srinivas KANDAGATLA
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE_MASK 0x1
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE_SHIFT 20
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE BIT(20)
+#define STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_DOUBLE_EDGE)
+#define STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_DOUBLE_EDGE)
Dito.
Post by Srinivas KANDAGATLA
+#define STIXXXX_PINCONF_RT_CLK_MASK 0x3
+#define STIXXXX_PINCONF_RT_CLK_SHIFT 18
+#define STIXXXX_PINCONF_RT_CLK BIT(18)
+#define STIXXXX_PINCONF_UNPACK_RT_CLK(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_CLK)
+#define STIXXXX_PINCONF_PACK_RT_CLK(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_CLK)
Dito.
Post by Srinivas KANDAGATLA
+/* RETIME_DELAY in Pico Secs */
+#define STIXXXX_PINCONF_RT_DELAY_MASK 0xffff
+#define STIXXXX_PINCONF_RT_DELAY_SHIFT 0
+#define STIXXXX_PINCONF_UNPACK_RT_DELAY(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_DELAY)
+#define STIXXXX_PINCONF_PACK_RT_DELAY(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_DELAY)
But here you need the special packed val to be passed,
so this looks good.
Post by Srinivas KANDAGATLA
+#endif /* __LINUX_DRIVERS_PINCTRL_STIXXXX_H */
Move the entire header into the drivers main .c file. Why complicate things?

Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-17 13:31:46 UTC
Permalink
Thankyou very much for the comments.
Post by Linus Walleij
On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This pinctrl driver manages both PIO and PIO-mux block using pinctrl,
pinconf, pinmux, gpio subsystems. All the pinctrl related config
information can only come from device trees.
OK that's a good approach!
Thankyou
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+- #gpio-cells : Should be one. The first cell is the pin number.
+- st,retime-in-delay : Should be array of delays in nsecs.
+- st,retime-out-delay : Should be array of delays in nsecs.
Please explain more verbosely what is meant by these
delays. in-delay of what? out-delay of what?
Am moving this to the driver too, as these tend to be constant per given
SOC.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+- st,retime-pin-mask : Should be mask to specify which pins can be retimed.
Explain what this "retimed" means.
I will explain this bit in more detail.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+- st,bank-name : Should be a name string for this bank.
Usually we only use an identifier, like a number for this, but
maybe you need this, so won't judge on it.
It's used for maintaining consistency with pin names from data sheet to
the pinctrl_pin_desc.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+- st,syscfg : phandle of the syscfg node.
This is pretty clever.
Thankyou.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+- st,syscfg-offsets : Should be a 5 cell entry which represent offset of altfunc,
+ output-enable, pull-up , open drain and retime registers in the syscfg bank
No please. Use the compatible string to determine which version of the
hardware this is and encode a register offset table into the driver instead.
We do not store register offsets in the device tree, it is not a datasheet
XML container you know...
Got it, I already moved this to the driver now. And its looking good.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+- delay is retime delay in pico seconds.
+ Possible values are: refer to retime-in/out-delays
Earlier it was given in nanoseconds.
I will fix this.
Post by Linus Walleij
And I still have no clue what "retiming" means.
I'm suspecting you cannot actually use generic pinconfig
due to all this retiming esoterica but atleast give it a thought.
Post by Srinivas KANDAGATLA
+- rt_clk :clk to be use for retime.
+ CLK_A
+ CLK_B
+ CLK_C
+ CLK_D
So this is selecting one of four available clock lines?
No, It's not related to driver clocks.
It's to do with the retiming. This part configures which clock to retime
output/input data to. CLK_A means retime output data to clkout[0] and
input data on clkin[0].

Will add more documentation on re-timing in general.
Post by Linus Walleij
Should this not interact with some clk bindings for your
clock tree?
Post by Srinivas KANDAGATLA
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 8f66924..0c040a3 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -169,6 +169,17 @@ config PINCTRL_SUNXI
select PINMUX
select GENERIC_PINCONF
+config PINCTRL_STIXXXX
As mentioned elsewhere STIXXXX is a bit too much X:es in.
Please come up with some better naming if possible.
Are you OK if I use pinctrl-st.c?
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+ bool "ST Microelectronics pin controller driver for STixxxx SoCs"
depends on OF
Ok, Will add it.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+ select PINMUX
+ select PINCONF
+ help
+ Say yes here to support pinctrl interface on STixxxx SOCs.
+ This driver is used to control both PIO block and PIO-mux
+ block to configure a pin.
+
+ If unsure, say N.
(...)
Post by Srinivas KANDAGATLA
+++ b/drivers/pinctrl/pinctrl-stixxxx.c
+struct stixxxx_gpio_port {
+ struct gpio_chip gpio_chip;
+ struct pinctrl_gpio_range range;
+ void __iomem *base;
+ struct device_node *of_node;
Why do you need this? The struct gpio_chip above can contain
the of_node can it not?
I remove the of_node as part of "simple-bus" cleanup from the pinctrl node.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+ const char *bank_name;
+};
+static struct stixxxx_gpio_port *gpio_ports[STIXXXX_MAX_GPIO_BANKS];
This is complicating things. Can't you just store the array of GPIO ports
*inside* the struct stixxxx_pinctrl container or something?
Already taken care from previous comment.
Post by Linus Walleij
(...)
Post by Srinivas KANDAGATLA
+/* Low level functions.. */
+static void stixxxx_pinconf_set_direction(struct stixxxx_pio_control *pc,
+ int pin_id, unsigned long config)
Why is this function called "*_set_direction" when it is also
messing with PU and OD?
_set_config would be more appropriate.
Yes, I will rename it.
Post by Linus Walleij
(The code looks fine.)
(...)
Post by Srinivas KANDAGATLA
+static void stixxxx_pinconf_set_retime_packed(
+ struct stixxxx_pio_control *pc,
+ unsigned long config, int pin)
+{
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+ struct regmap_field **regs;
+ unsigned int values[2];
+ unsigned long mask;
+ int i, j;
+ int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+ int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+ int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+ int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+ int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+ unsigned long delay = stixxxx_pinconf_delay_to_bit(
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+ pc->rt_params, config);
As you can see it's a bit excess of "X" above. Hard to read.
Ok, Will make it bool.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+ unsigned long rt_cfg =
+ ((clk & 1) << offset->clk1notclk0_offset) |
+ ((clknotdata & 1) << offset->clknotdata_offset) |
+ ((delay & 1) << offset->delay_lsb_offset) |
+ (((delay >> 1) & 1) << offset->delay_msb_offset) |
+ ((double_edge & 1) << offset->double_edge_offset) |
+ ((invertclk & 1) << offset->invertclk_offset) |
+ ((retime & 1) << offset->retime_offset);
This is looking strange. Just strange.
Comments are needed I think. For example why
arey >> 1 on delay all of a sudden?
I would try to make clk, clknotdata, delay etc into bools.
#include <linux/bitops.h>
unsigned long rt_cfg = 0;
if (clk)
rt_cfg |= BIT(offset->clk1notclk0_offset);
if (clknotdata)
rt_cfg |= BIT(offset->clknotdata_offset);
etc.
Yes, Looks sensible, I will try these changes and see how it turns up.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+ regs = pc->retiming;
+ regmap_field_read(regs[0], &values[0]);
+ regmap_field_read(regs[1], &values[1]);
+
+ for (i = 0; i < 2; i++) {
+ mask = BIT(pin);
+ for (j = 0; j < 4; j++) {
+ if (rt_cfg & 1)
+ values[i] |= mask;
+ else
+ values[i] &= ~mask;
+ mask <<= 8;
+ rt_cfg >>= 1;
+ }
+ }
2? 4? 8? Not quite readable with so many magic constants.
Is this "8" identical to STIXXXX_GPIO_PINS_PER_PORT?
I agree, all these constants should be #defined in a readable way, and I
will do it. (for all the comments related to constants ...)
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+static int stixxxx_pinconf_get_retime_packed(
+ struct stixxxx_pio_control *pc,
+ int pin, unsigned long *config)
+{
+ const struct stixxxx_retime_params *rt_params = pc->rt_params;
+ const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+ unsigned long delay_bits, delay, rt_reduced;
+ unsigned int rt_value[2];
+ int i, j;
+ int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+ regmap_field_read(pc->retiming[0], &rt_value[0]);
+ regmap_field_read(pc->retiming[1], &rt_value[1]);
+
+ rt_reduced = 0;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 4; j++) {
+ if (rt_value[i] & (1<<((8*j)+pin)))
+ rt_reduced |= 1 << ((i*4)+j);
+ }
+ }
Urgh 2, 4, 8??
What is happening here ... atleast a big comment
explaining the logic would be helpful. Some kind of
matrix traversal seem to be involved.
Yes, I will add a decent comment here.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+ STIXXXX_PINCONF_PACK_RT(*config,
+ (rt_reduced >> offset->retime_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_CLK(*config,
+ (rt_reduced >> offset->clk1notclk0_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config,
+ (rt_reduced >> offset->clknotdata_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config,
+ (rt_reduced >> offset->double_edge_offset) & 1);
+ STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config,
+ (rt_reduced >> offset->invertclk_offset) & 1);
I would rewrite this like
if ((rt_reduced >> offset->retime_offset) & 1)
STIXXXX_PINCONF_PACK_RT(*config, 1);
See further comments on these macros below.
if ((rt_reduced >> offset->retime_offset) & 1)
STIXXXX_PINCONF_PACK_RT(*config);
Simpler.
I will do it.
Post by Linus Walleij
(...)
Post by Srinivas KANDAGATLA
+static void stixxxx_gpio_direction(unsigned int gpio, unsigned int direction)
+{
+ int port_num = stixxxx_gpio_port(gpio);
+ int offset = stixxxx_gpio_pin(gpio);
+ struct stixxxx_gpio_port *port = gpio_ports[port_num];
+ int i = 0;
+
+ for (i = 0; i <= 2; i++) {
+ if (direction & BIT(i))
+ writel(BIT(offset), port->base + REG_PIO_SET_PC(i));
+ else
+ writel(BIT(offset), port->base + REG_PIO_CLR_PC(i));
+ }
Can you explain here in a comment why the loop has to hit
bits 0, 1 and 2 in this register?
Yes, I will add the comments behind the logic of this.
Post by Linus Walleij
(...)
Post by Srinivas KANDAGATLA
+static int stixxxx_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+
+ return (readl(port->base + REG_PIO_PIN) >> offset) & 1;
return !!(readl(port->base + REG_PIO_PIN) & BIT(offset));
Interesting and very neat.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+static void stixxxx_pctl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+}
Isn't this optional? And don't you need to free this?
Its not optional because pinctrl_check_ops returns -EINVAL if set to NULL.

I don't need to free it because its a devm_kzalloc.
Post by Linus Walleij
(...)
Post by Srinivas KANDAGATLA
+static void stixxxx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin_id)
+{
+ unsigned long config;
+ stixxxx_pinconf_get(pctldev, pin_id, &config);
+
+ seq_printf(s, "[OE:%ld,PU:%ld,OD:%ld]\n"
+ "\t\t[retime:%ld,invclk:%ld,clknotdat:%ld,"
+ "de:%ld,rt-clk:%ld,rt-delay:%ld]",
+ STIXXXX_PINCONF_UNPACK_OE(config),
+ STIXXXX_PINCONF_UNPACK_PU(config),
+ STIXXXX_PINCONF_UNPACK_OD(config),
+ STIXXXX_PINCONF_UNPACK_RT(config),
+ STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config),
+ STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config),
+ STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config),
+ STIXXXX_PINCONF_UNPACK_RT_CLK(config),
+ STIXXXX_PINCONF_UNPACK_RT_DELAY(config));
+}
This looks real nice, but is the output human-friendly?
I will see, If I can come up with a better format.
Post by Linus Walleij
Well maybe the format needs to be compact like this...
Post by Srinivas KANDAGATLA
+ if (of_device_is_compatible(np, "st,stih415-pinctrl")) {
+ rt_offset = devm_kzalloc(info->dev,
+ sizeof(*rt_offset), GFP_KERNEL);
+
+ if (!rt_offset)
+ return -ENOMEM;
+
+ rt_offset->clk1notclk0_offset = 0;
+ rt_offset->delay_lsb_offset = 2;
+ rt_offset->delay_msb_offset = 3;
+ rt_offset->invertclk_offset = 4;
+ rt_offset->retime_offset = 5;
+ rt_offset->clknotdata_offset = 6;
+ rt_offset->double_edge_offset = 7;
This looks awkward and complicated.
Why not just #define these offsets and use them
directly in the code?
This is more specific to a SOC.
This information now comes as part of the SOC specific compatible node data.

Like this:

const struct stixxxx_retime_offset stih415_retime_offset = {
.clk1notclk0_offset = 0,
.delay_lsb_offset = 2,
.delay_msb_offset = 3,
.invertclk_offset = 4,
.retime_offset = 5,
.clknotdata_offset = 6,
.double_edge_offset = 7,
};

unsigned int stih415_input_delays[] = {0, 500, 1000, 1500};
unsigned int stih415_output_delays[] = {0, 1000, 2000, 3000};

static const struct stixxxx_pctl_data stih415_sbc_data = {
.rt_style = stixxxx_retime_style_packed,
.rt_offset = &stih415_retime_offset,
.input_delays = stih415_input_delays,
.ninput_delays = 4,
.output_delays = stih415_output_delays,
.noutput_delays = 4,
.alt = 0, .oe = 5, .pu = 7, .od = 9, .rt = 16,
};
static struct of_device_id stixxxx_pctl_of_match[] = {
{ .compatible = "st,stih415-sbc-pinctrl", .data = &stih415_sbc_data },
};
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+static int stixxxx_pctl_dt_init(struct stixxxx_pinctrl *info,
+ struct device_node *np)
+{
+ struct stixxxx_pio_control *pc;
+ struct stixxxx_retime_params *rt_params;
+ struct device *dev = info->dev;
+ struct regmap *regmap;
+ unsigned int i = 0;
+ struct device_node *child = NULL;
+ u32 alt_syscfg, oe_syscfg, pu_syscfg, od_syscfg, rt_syscfg;
+ u32 syscfg_offsets[5];
+ u32 msb, lsb;
+
+ pc = devm_kzalloc(dev, sizeof(*pc) * info->nbanks, GFP_KERNEL);
+ rt_params = devm_kzalloc(dev, sizeof(*rt_params), GFP_KERNEL);
+
+ if (!pc || !rt_params)
+ return -ENOMEM;
+
+ regmap = syscfg_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (!regmap) {
+ dev_err(dev, "No syscfg phandle specified\n");
+ return -ENOMEM;
+ }
+ info->regmap = regmap;
+ info->pio_controls = pc;
+ if (stixxxx_pinconf_dt_parse_rt_params(info, np, rt_params))
+ return -ENOMEM;
+
+ if (of_property_read_u32_array(np, "st,syscfg-offsets",
+ syscfg_offsets, 5)) {
+ dev_err(dev, "Syscfg offsets not found\n");
+ return -EINVAL;
+ }
+ alt_syscfg = syscfg_offsets[0];
+ oe_syscfg = syscfg_offsets[1];
+ pu_syscfg = syscfg_offsets[2];
+ od_syscfg = syscfg_offsets[3];
+ rt_syscfg = syscfg_offsets[4];
This isn't looking any fun either.
#defining the offsets avoid all this strange boilerplate.
Post by Srinivas KANDAGATLA
+ lsb = 0;
+ msb = 7;
And this.
Post by Srinivas KANDAGATLA
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ struct reg_field alt_reg =
+ REG_FIELD(4 * alt_syscfg++, 0, 31);
+ struct reg_field oe_reg =
+ REG_FIELD(4 * oe_syscfg, lsb, msb);
+ struct reg_field pu_reg =
+ REG_FIELD(4 * pu_syscfg, lsb, msb);
+ struct reg_field od_reg =
+ REG_FIELD(4 * od_syscfg, lsb, msb);
+ pc[i].rt_params = rt_params;
+
+ pc[i].alt = devm_regmap_field_alloc(dev,
+ regmap, alt_reg);
+ pc[i].oe = devm_regmap_field_alloc(dev,
+ regmap, oe_reg);
+ pc[i].pu = devm_regmap_field_alloc(dev,
+ regmap, pu_reg);
+ pc[i].od = devm_regmap_field_alloc(dev,
+ regmap, od_reg);
+
+ if (IS_ERR(pc[i].alt) || IS_ERR(pc[i].oe)
+ || IS_ERR(pc[i].pu) || IS_ERR(pc[i].od))
+ goto failed;
+
+ of_property_read_u32(child, "st,retime-pin-mask",
+ &pc[i].rt_pin_mask);
+
+ stixxxx_pctl_dt_get_retime_conf(info, &pc[i],
+ &rt_syscfg);
+ i++;
+ if (msb == 31) {
+ oe_syscfg++;
+ pu_syscfg++;
+ od_syscfg++;
+ lsb = 0;
+ msb = 7;
+ } else {
+ lsb += 8;
+ msb += 8;
+ }
Can you explain with a comment what is happening here.
Most of this code disappeared as part of merging gpio and pinctrl
platformdriver in to one.
However I will make sure I add more comments in this area.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+static struct pinctrl_gpio_range *find_gpio_range(struct device_node *np)
+{
+ int i;
+ for (i = 0; i < STIXXXX_MAX_GPIO_BANKS; i++)
+ if (gpio_ports[i]->of_node == np)
+ return &gpio_ports[i]->range;
+
+ return NULL;
+}
This looks a bit like it's duplicating pinctrl_find_gpio_range_from_pin()
or similar already available from the pinctrl core. But it seems you
may need it here in this case.
You are right, I should have used pinctrl_find_gpio_range_from_pin.

This code disappeared too as part of merging gpio and pinctrl platform
driver in to one.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+static int stixxxx_pctl_probe(struct platform_device *pdev)
(...)
Post by Srinivas KANDAGATLA
+static int stixxxx_gpio_probe(struct platform_device *pdev)
(...)
Post by Srinivas KANDAGATLA
+static struct of_device_id stixxxx_gpio_of_match[] = {
+ { .compatible = "st,stixxxx-gpio", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_gpio_driver = {
+ .driver = {
+ .name = "st-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stixxxx_gpio_of_match),
+ },
+ .probe = stixxxx_gpio_probe,
+};
+
+static struct of_device_id stixxxx_pctl_of_match[] = {
+ { .compatible = "st,stixxxx-pinctrl",},
+ { .compatible = "st,stih415-pinctrl",},
+ { .compatible = "st,stih416-pinctrl",},
+ { /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_pctl_driver = {
+ .driver = {
+ .name = "st-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stixxxx_pctl_of_match),
+ },
+ .probe = stixxxx_pctl_probe,
+};
Why do you need separate nodes and probe functions for the
pinctrl and GPIO? Can't you just have a single pinctrl node?
Post by Srinivas KANDAGATLA
+static int __init stixxxx_pctl_init(void)
+{
+ int ret = platform_driver_register(&stixxxx_gpio_driver);
+ if (ret)
+ return ret;
+ return platform_driver_register(&stixxxx_pctl_driver);
+}
Especially since you're just registering them after each other.
Maybe you could have the GPIO nodes as children inside the
pinctrl node and iterate over with for_each_child_of_node()?
I'm not requiring you rewrite this, just that you give it a thought.
Arnd suggested the same thing, and I have already done this change and
it did clean up lot of code and device tree too.
Now the device tree for pinctrl looks much simple.

pin-controller-sbc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "st,stih415-sbc-pinctrl";
st,syscfg = <&syscfg_sbc>;
ranges = <0 0xfe610000 0x5000>;

PIO0: ***@fe610000 {
gpio-controller;
#gpio-cells = <1>;
reg = <0 0x100>;
st,bank-name = "PIO0";
};

...
};
Post by Linus Walleij
(...)
Post by Srinivas KANDAGATLA
+++ b/drivers/pinctrl/pinctrl-stixxxx.h
@@ -0,0 +1,197 @@
+
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+#define __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+
+enum stixxxx_retime_style {
+ stixxxx_retime_style_none,
+ stixxxx_retime_style_packed,
+ stixxxx_retime_style_dedicated,
+};
+
+/* Byte positions in 2 syscon words, starts from 0 */
+struct stixxxx_retime_offset {
+ int retime_offset;
+ int clk1notclk0_offset;
+ int clknotdata_offset;
+ int double_edge_offset;
+ int invertclk_offset;
+ int delay_lsb_offset;
+ int delay_msb_offset;
+};
+
+struct stixxxx_retime_params {
+ const struct stixxxx_retime_offset *retime_offset;
+ unsigned int *delay_times_in;
+ int num_delay_times_in;
+ unsigned int *delay_times_out;
+ int num_delay_times_out;
+};
+
+struct stixxxx_pio_control {
+ enum stixxxx_retime_style rt_style;
+ u32 rt_pin_mask;
+ const struct stixxxx_retime_params *rt_params;
+ struct regmap_field *alt;
+ struct regmap_field *oe, *pu, *od;
+ struct regmap_field *retiming[8];
+};
Are these used outside of the driver? If not, move it into the
driver .c file.
Yes, I will move this to driver.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+#define STIXXXX_GPIO_PINS_PER_PORT 8
Does *any* of this have to be in the header file? If not, move it
into the driver instead, so the reader don't have to shift between several
files when reading the driver code.
Post by Srinivas KANDAGATLA
+#define stixxxx_gpio_port(gpio) ((gpio) / STIXXXX_GPIO_PINS_PER_PORT)
+#define stixxxx_gpio_pin(gpio) ((gpio) % STIXXXX_GPIO_PINS_PER_PORT)
Move these three #defines into the driver and convert the
two last ones to static inlines instead. Easier to maintain.
Ok, I will do it.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+#define STIXXXX_PINCONF_UNPACK(conf, param)\
+ ((conf >> STIXXXX_PINCONF_ ##param ##_SHIFT) \
+ & STIXXXX_PINCONF_ ##param ##_MASK)
+
+#define STIXXXX_PINCONF_PACK(conf, val, param) (conf |=\
+ ((val & STIXXXX_PINCONF_ ##param ##_MASK) << \
+ STIXXXX_PINCONF_ ##param ##_SHIFT))
+
+/* Output enable */
+#define STIXXXX_PINCONF_OE_MASK 0x1
+#define STIXXXX_PINCONF_OE_SHIFT 27
+#define STIXXXX_PINCONF_OE BIT(27)
+#define STIXXXX_PINCONF_UNPACK_OE(conf) STIXXXX_PINCONF_UNPACK(conf, OE)
+#define STIXXXX_PINCONF_PACK_OE(conf, val) STIXXXX_PINCONF_PACK(conf, val, OE)
For all of these macros: why are you suppying an argument that can only
be 0 or 1?
#define STIXXXX_PINCONF_PACK_OE(conf) STIXXXX_PINCONF_PACK(conf, 1, OE)
And only call it if you want to enable the feature, else avoid calling it.
There is no point of setting bits to zero with so much adoo.
Yes, I will try this and see how it will look like.
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+/* RETIME_DELAY in Pico Secs */
+#define STIXXXX_PINCONF_RT_DELAY_MASK 0xffff
+#define STIXXXX_PINCONF_RT_DELAY_SHIFT 0
+#define STIXXXX_PINCONF_UNPACK_RT_DELAY(conf) \
+ STIXXXX_PINCONF_UNPACK(conf, RT_DELAY)
+#define STIXXXX_PINCONF_PACK_RT_DELAY(conf, val) \
+ STIXXXX_PINCONF_PACK(conf, val, RT_DELAY)
But here you need the special packed val to be passed,
so this looks good.
Post by Srinivas KANDAGATLA
+#endif /* __LINUX_DRIVERS_PINCTRL_STIXXXX_H */
Move the entire header into the drivers main .c file. Why complicate things?
yes, I will move the full header contents to c file.

Thanks,
srini
Post by Linus Walleij
Yours,
Linus Walleij
Linus Walleij
2013-06-17 16:27:28 UTC
Permalink
On Mon, Jun 17, 2013 at 3:31 PM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
Post by Linus Walleij
Post by Srinivas KANDAGATLA
+config PINCTRL_STIXXXX
As mentioned elsewhere STIXXXX is a bit too much X:es in.
Please come up with some better naming if possible.
Are you OK if I use pinctrl-st.c?
It seems to no be taken so OK :-)

The best choice is just the name of the IP block,
something unique. I would consider trying to ask the
hardware engineer writing that pinctrl block what name
s/he prefer on it, if not possible just go with pinctrl-st.c.

The rest seems to be addressed nicely, waiting for the
next iteration!

Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-10 09:26:21 UTC
Permalink
Michal Simek
2013-06-10 09:55:16 UTC
Permalink
Michal Simek
2013-06-10 11:08:35 UTC
Permalink
Srinivas KANDAGATLA
2013-06-10 11:46:59 UTC
Permalink
On 10/06/13 12:15, Michal Simek wrote:

Thankyou for your comments,
Hi,
hmm - that's a nice bug that thunderbird is not able to send this email. :-(
Let's comment it again via gmail.
diff --git a/arch/arm/boot/dts/stih415.dtsi
b/arch/arm/boot/dts/stih415.dtsi
new file mode 100644
index 0000000..6dcf5b4
--- /dev/null
+++ b/arch/arm/boot/dts/stih415.dtsi
...
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+ ranges;
+ compatible = "simple-bus";
Rob and Grant: what's the purpose of SoC node.
It seems to me odd that SoC is compatible with simple-bus.
All the drivers on this SOC are based on platform bus, so we use
simple-bus, here.
diff --git a/arch/arm/boot/dts/stih41x.dtsi
b/arch/arm/boot/dts/stih41x.dtsi
new file mode 100644
index 0000000..7321403
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x.dtsi
@@ -0,0 +1,38 @@
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ };
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ };
+ };
+
I believe your SoC also has a bus here.
It does but there is no active driver to manage it.
--- /dev/null
+++ b/arch/arm/mach-stixxxx/board-dt.c
@@ -0,0 +1,47 @@
+
+void __init stih41x_l2x0_init(void)
+{
+ u32 way_size = 0x4;
+ u32 aux_ctrl;
+
+ aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
+ (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
#include <linux/bitops.h>
Linus Walleij would write use BIT() here
I will use BIT() macro.
diff --git a/arch/arm/mach-stixxxx/headsmp.S
b/arch/arm/mach-stixxxx/headsmp.S
new file mode 100644
index 0000000..3dd5c04
--- /dev/null
+++ b/arch/arm/mach-stixxxx/headsmp.S
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/plat-stixxxx/headsmp.S
+ .long pen_release
check that your SoC has no option to start/reset cpus separately.
If yes, then you shouldn't use pen_release.
We discussed this with Russel some days ago.
No, stih41x series can't reset the cores separately.
diff --git a/arch/arm/mach-stixxxx/platsmp.c
b/arch/arm/mach-stixxxx/platsmp.c
new file mode 100644
index 0000000..ffc40c0
--- /dev/null
+++ b/arch/arm/mach-stixxxx/platsmp.c
@@ -0,0 +1,117 @@
+/*
+ * arch/arm/plat-stixxxx/platsmp.c
wrong.
Left over, will clean it up in next version.
+ * arch/arm/plat-stixxxx/platsmp.c
incorrect.
Left over, will clean it up in next version.
+extern struct smp_operations stixxxx_smp_ops;
+extern void __iomem *stixxxx_scu_base_addr;
Unused variable in this patch.
yes, I will remove stixxxx_scu_base_addr.

thanks,
srini
Russell King - ARM Linux
2013-06-10 23:19:34 UTC
Permalink
Post by Srinivas KANDAGATLA
+ aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
+ (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
#include <linux/bitops.h>
Linus Walleij would write use BIT() here
I will use BIT() macro.
Without checking those fields... BIT() is only appropriate if you're
really talking about single bits. If you have a field of more than a
single bit which you happen to be setting to '1' then it's not
appropriate to use BIT().
Srinivas KANDAGATLA
2013-06-11 06:50:31 UTC
Permalink
Post by Russell King - ARM Linux
Post by Srinivas KANDAGATLA
+ aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
+ (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
#include <linux/bitops.h>
Linus Walleij would write use BIT() here
I will use BIT() macro.
Without checking those fields... BIT() is only appropriate if you're
really talking about single bits. If you have a field of more than a
single bit which you happen to be setting to '1' then it's not
appropriate to use BIT().
You are right, It does not make sense to use BIT() macro for field which
has more than 1 bit. I think using mix of both BIT() and the old style
will make code look bit confusing to reader, Also no other mach code in
the kernel use BIT while configuring L2 controller. So am going to drop
the idea of using BIT here and leave the code as it is.

Thanks,
srini
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Russell King - ARM Linux
2013-06-13 11:56:40 UTC
Permalink
Post by Srinivas KANDAGATLA
You are right, It does not make sense to use BIT() macro for field which
has more than 1 bit. I think using mix of both BIT() and the old style
will make code look bit confusing to reader, Also no other mach code in
the kernel use BIT while configuring L2 controller. So am going to drop
the idea of using BIT here and leave the code as it is.
I'd suggest putting a comment in the code to that effect. With the way
"cleanups" get done, I wouldn't be surprised if this attracts a lot of
people wanting to do a trivial "1 << bit" -> "BIT(bit)" conversions.

One of the problems of open source is that you can say "no" to a patch
like that until you're blue in the face, but it will eventually make
its way in via some path.

Just one of the reasons I consider BIT() to be evil and an inappropriate
macro.
Srinivas KANDAGATLA
2013-06-13 12:41:33 UTC
Permalink
Post by Russell King - ARM Linux
Post by Srinivas KANDAGATLA
You are right, It does not make sense to use BIT() macro for field which
has more than 1 bit. I think using mix of both BIT() and the old style
will make code look bit confusing to reader, Also no other mach code in
the kernel use BIT while configuring L2 controller. So am going to drop
the idea of using BIT here and leave the code as it is.
I'd suggest putting a comment in the code to that effect. With the way
"cleanups" get done, I wouldn't be surprised if this attracts a lot of
people wanting to do a trivial "1 << bit" -> "BIT(bit)" conversions.
Hmm... I can add a comment for them.
Post by Russell King - ARM Linux
One of the problems of open source is that you can say "no" to a patch
like that until you're blue in the face, but it will eventually make
its way in via some path.
Just one of the reasons I consider BIT() to be evil and an inappropriate
macro.
Linus Walleij
2013-06-13 12:47:27 UTC
Permalink
On Tue, Jun 11, 2013 at 1:19 AM, Russell King - ARM Linux
Post by Russell King - ARM Linux
Post by Srinivas KANDAGATLA
+ aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
+ (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
+ (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
#include <linux/bitops.h>
Linus Walleij would write use BIT() here
I will use BIT() macro.
Without checking those fields... BIT() is only appropriate if you're
really talking about single bits. If you have a field of more than a
single bit which you happen to be setting to '1' then it's not
appropriate to use BIT().
This is true. Luckily I didn't push for it myself this time.

However, on a related key we have this hidden away in MFD
drivers/mfd/dbx500-prcmu-regs.h:

#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))

It's used like so:

#define PRCM_PLL_FREQ_D_MASK BITS(0, 7)

So you can define an multi-bit mask with a macro like that.

If there is interest in a construct like this I can make a patch to
move this thing to <linux/bitops.h>.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Linus Walleij
2013-06-10 12:43:03 UTC
Permalink
On Mon, Jun 10, 2013 at 11:26 AM, Srinivas KANDAGATLA
The STiH415 is the next generation of HD, AVC set-top box processors for
satellite, cable, terrestrial and IP-STB markets. It is an ARM Cortex-A9
1.0 GHz, dual-core CPU.
(...)
+ soc {
+ pin-controller-sbc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,stih415-pinctrl", "simple-bus";
Why is the pin controller be a simple bus?

Maybe obvious, I'm not 100% familiar with when we use this...
+ pin-controller-front {
(...)
+ pin-controller-rear {
(...)
+ pin-controller-left {
(...)
+ pin-controller-right {
Please explain these orientations in some comment in the device
tree, I'm half-guessing that it's about the edges around the chip so
the PIO* names are actually pad names.

I would suggest you use the names north/south/west/east
if this is the case since left and right etc are relative measures.
(This terminology is used on e.g. dance mats for console games...)

If these names are from the datasheets by all means keep them.
+++ b/arch/arm/boot/dts/stixxxx-pincfg.h
@@ -0,0 +1,94 @@
+#ifndef _STIXXXX_PINCFG_H_
+#define _STIXXXX_PINCFG_H_
+
+/* Alternate functions */
+#define ALT1 1
+#define ALT2 2
+#define ALT3 3
+#define ALT4 4
+#define ALT5 5
+#define ALT6 6
+#define ALT7 7
Why is this part of the DT definitions? In the pinctrl world this
is an intrinsic detail on how groups and functions are associated,
not something that you hard-code into the device tree. The
device tree should state how to combine functions with groups
and those will be strings, not numerals.

Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-10 16:38:54 UTC
Permalink
Post by Linus Walleij
On Mon, Jun 10, 2013 at 11:26 AM, Srinivas KANDAGATLA
The STiH415 is the next generation of HD, AVC set-top box processors for
satellite, cable, terrestrial and IP-STB markets. It is an ARM Cortex-A9
1.0 GHz, dual-core CPU.
(...)
+ soc {
+ pin-controller-sbc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,stih415-pinctrl", "simple-bus";
Why is the pin controller be a simple bus?
As gpio banks are children of this node, the gpio driver associated with
these banks can only be probed if the parent of the node has simple bus
compatible string.
Post by Linus Walleij
Maybe obvious, I'm not 100% familiar with when we use this...
+ pin-controller-front {
(...)
+ pin-controller-rear {
(...)
+ pin-controller-left {
(...)
+ pin-controller-right {
Please explain these orientations in some comment in the device
tree, I'm half-guessing that it's about the edges around the chip so
the PIO* names are actually pad names.
I would suggest you use the names north/south/west/east
if this is the case since left and right etc are relative measures.
(This terminology is used on e.g. dance mats for console games...)
If these names are from the datasheets by all means keep them.
I will add more comments in this area, the naming comes from
data-sheets. I have no choice.
Post by Linus Walleij
+++ b/arch/arm/boot/dts/stixxxx-pincfg.h
@@ -0,0 +1,94 @@
+#ifndef _STIXXXX_PINCFG_H_
+#define _STIXXXX_PINCFG_H_
+
+/* Alternate functions */
+#define ALT1 1
+#define ALT2 2
+#define ALT3 3
+#define ALT4 4
+#define ALT5 5
+#define ALT6 6
+#define ALT7 7
Why is this part of the DT definitions? In the pinctrl world this
is an intrinsic detail on how groups and functions are associated,
not something that you hard-code into the device tree. The
device tree should state how to combine functions with groups
and those will be strings, not numerals.
If this is wrong way to do things, I would like to fix this.
Functions in ST are alt-functions which are generally from alt0-alt7.
I use this property in the pinctrl group as shown in this simple example:

pinctrl_sbc_serial1:sbc_serial1 {
st,function = <ALT3>;
st,pins {
tx = <&PIO2 6 OUT>;
rx = <&PIO2 7 IN>;
};
};

To configure the group in alternate function 3.
You suggest that this should be
st,function = "alt3"; it does not look any different to what I have.

Looking at some of existing pinctrl nodes, I can see like:
samsung,pin-function = <2>;
or
brcm,function = <4>; /* alt0 */

Sorry ...Am I missing some thing?

Thanks,
srini
Post by Linus Walleij
Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-14 07:31:56 UTC
Permalink
+++ b/arch/arm/boot/dts/stixxxx-pincfg.h
@@ -0,0 +1,94 @@
+#ifndef _STIXXXX_PINCFG_H_
+#define _STIXXXX_PINCFG_H_
+
+/* Alternate functions */
+#define ALT1 1
+#define ALT2 2
+#define ALT3 3
+#define ALT4 4
+#define ALT5 5
+#define ALT6 6
+#define ALT7 7
Why is this part of the DT definitions? In the pinctrl world this
is an intrinsic detail on how groups and functions are associated,
not something that you hard-code into the device tree. The
device tree should state how to combine functions with groups
and those will be strings, not numerals.
Hi Linus,
I would like to get correct understanding of the point your raised here.
I use these ALT function values in "st,function" property for pinctrl
group as shown in this simple example:

pinctrl_sbc_serial1:sbc_serial1 {
st,function = <ALT3>;
st,pins {
tx = <&PIO2 6 OUT>;
rx = <&PIO2 7 IN>;
};
};

If I do something like what rockchip pinctrl did the pinctrl group will
look like.

pinctrl_sbc_serial1:sbc_serial1 {
st,pins {
tx = <&PIO2 6 OUT ALT3>;
rx = <&PIO2 7 IN ALT3>;
};
};

Is this the right way to do it?

Thanks,
srini
Linus Walleij
2013-06-19 18:59:34 UTC
Permalink
On Fri, Jun 14, 2013 at 9:31 AM, Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
+++ b/arch/arm/boot/dts/stixxxx-pincfg.h
@@ -0,0 +1,94 @@
+#ifndef _STIXXXX_PINCFG_H_
+#define _STIXXXX_PINCFG_H_
+
+/* Alternate functions */
+#define ALT1 1
+#define ALT2 2
+#define ALT3 3
+#define ALT4 4
+#define ALT5 5
+#define ALT6 6
+#define ALT7 7
Why is this part of the DT definitions? In the pinctrl world this
is an intrinsic detail on how groups and functions are associated,
not something that you hard-code into the device tree. The
device tree should state how to combine functions with groups
and those will be strings, not numerals.
Hi Linus,
I would like to get correct understanding of the point your raised here.
I use these ALT function values in "st,function" property for pinctrl
pinctrl_sbc_serial1:sbc_serial1 {
st,function = <ALT3>;
st,pins {
tx = <&PIO2 6 OUT>;
rx = <&PIO2 7 IN>;
};
};
If I do something like what rockchip pinctrl did the pinctrl group will
look like.
pinctrl_sbc_serial1:sbc_serial1 {
st,pins {
tx = <&PIO2 6 OUT ALT3>;
rx = <&PIO2 7 IN ALT3>;
};
};
Is this the right way to do it?
Basically there is no right way to do it since we haven't been able
to agree on a common way to represent pin controllers in the
device tree.

Those I have looked closer at tend to encode the selected
function/group as a string rather than a numeral though.

Yours,
Linus Walleij
Srinivas KANDAGATLA
2013-06-10 09:27:32 UTC
Permalink
This patch adds low level debug uart support to stixxxx based SOCs.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-***@public.gmane.org>
CC: Arnd Bergmann <arnd-***@public.gmane.org>
---
arch/arm/Kconfig.debug | 38 +++++++++++++++++++++++
arch/arm/include/debug/stixxxx.S | 61 ++++++++++++++++++++++++++++++++++++++
arch/arm/mach-stixxxx/board-dt.c | 2 +
3 files changed, 101 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/include/debug/stixxxx.S

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 1d41908..cc98ef3 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -483,6 +483,16 @@ choice
This option selects UART0 on VIA/Wondermedia System-on-a-chip
devices, including VT8500, WM8505, WM8650 and WM8850.

+ config DEBUG_STIXXXX_UART
+ depends on ARCH_STIXXXX
+ bool "Use StiH415/416 ASC for low-level debug"
+ help
+ Say Y here if you want kernel low-level debugging support
+ on StiH415/416 based platforms like B2000, B2020.
+ It support UART2 and SBC_UART1.
+
+ If unsure, say N.
+
config DEBUG_LL_UART_NONE
bool "No low-level debugging UART"
depends on !ARCH_MULTIPLATFORM
@@ -617,6 +627,33 @@ choice

endchoice

+choice
+ prompt "Low-level debug console UART"
+ depends on DEBUG_LL && DEBUG_STIXXXX_UART
+
+ config STIH41X_DEBUG_ASC2
+ bool "ASC2 UART"
+ help
+ Say Y here if you want kernel low-level debugging support
+ on STiH415/416 based platforms like b2000, which has
+ default UART wired up to ASC2.
+
+ If unsure, say N.
+
+ config STIH41X_DEBUG_SBC_ASC1
+ bool "SBC ASC1 UART"
+ help
+ Say Y here if you want kernel low-level debugging support
+ on STiH415/416 based platforms like b2020. which has
+ default UART wired up to SBC ASC1.
+
+ If unsure, say N.
+
+endchoice
+
+
+
+
config DEBUG_LL_INCLUDE
string
default "debug/bcm2835.S" if DEBUG_BCM2835
@@ -641,6 +678,7 @@ config DEBUG_LL_INCLUDE
DEBUG_MMP_UART3
default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
default "debug/socfpga.S" if DEBUG_SOCFPGA_UART
+ default "debug/stixxxx.S" if DEBUG_STIXXXX_UART
default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
default "debug/tegra.S" if DEBUG_TEGRA_UART
default "debug/ux500.S" if DEBUG_UX500_UART
diff --git a/arch/arm/include/debug/stixxxx.S b/arch/arm/include/debug/stixxxx.S
new file mode 100644
index 0000000..7bc02a7
--- /dev/null
+++ b/arch/arm/include/debug/stixxxx.S
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/include/debug/stixxxx.S
+ *
+ * Debugging macro include header
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define STIH41X_COMMS_BASE 0xfed00000
+#define STIH41X_ASC2_BASE (STIH41X_COMMS_BASE+0x32000)
+
+#define STIH41X_SBC_LPM_BASE 0xfe400000
+#define STIH41X_SBC_COMMS_BASE (STIH41X_SBC_LPM_BASE + 0x100000)
+#define STIH41X_SBC_ASC1_BASE (STIH41X_SBC_COMMS_BASE + 0x31000)
+
+
+#define VIRT_ADDRESS(x) (x - 0x1000000)
+
+#if IS_ENABLED(CONFIG_STIH41X_DEBUG_ASC2)
+#define DEBUG_LL_UART_BASE STIH41X_ASC2_BASE
+#endif
+
+#if IS_ENABLED(CONFIG_STIH41X_DEBUG_SBC_ASC1)
+#define DEBUG_LL_UART_BASE STIH41X_SBC_ASC1_BASE
+#endif
+
+#ifndef DEBUG_LL_UART_BASE
+#error "DEBUG UART is not Configured"
+#endif
+
+#define ASC_TX_BUF_OFF 0x04
+#define ASC_CTRL_OFF 0x0c
+#define ASC_STA_OFF 0x14
+
+#define ASC_STA_TX_FULL (1<<9)
+#define ASC_STA_TX_EMPTY (1<<1)
+
+
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =DEBUG_LL_UART_BASE @ physical base
+ ldr \rv, =VIRT_ADDRESS(DEBUG_LL_UART_BASE) @ virt base
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx, #ASC_TX_BUF_OFF]
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #ASC_STA_OFF]
+ tst \rd, #ASC_STA_TX_FULL
+ bne 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #ASC_STA_OFF]
+ tst \rd, #ASC_STA_TX_EMPTY
+ beq 1001b
+ .endm
diff --git a/arch/arm/mach-stixxxx/board-dt.c b/arch/arm/mach-stixxxx/board-dt.c
index 2b2552e..2482d139 100644
--- a/arch/arm/mach-stixxxx/board-dt.c
+++ b/arch/arm/mach-stixxxx/board-dt.c
@@ -11,6 +11,7 @@
#include <linux/clocksource.h>
#include <linux/irq.h>
#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
#include <asm/mach/arch.h>

#include "smp.h"
@@ -42,6 +43,7 @@ static const char *stih41x_dt_match[] __initdata = {
};

DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree")
+ .map_io = debug_ll_io_init,
.init_time = stih41x_timer_init,
.smp = smp_ops(stixxxx_smp_ops),
.dt_compat = stih41x_dt_match,
--
1.7.6.5
Srinivas KANDAGATLA
2013-06-10 09:27:57 UTC
Permalink
This patch adds stih415 and stih416 support to multi_v7_defconfig.

Signed-off-by: Srinivas Kandagatla <***@st.com>
CC: Arnd Bergmann <***@arndb.de>
---
arch/arm/configs/multi_v7_defconfig | 32 +++++++++++++++-----------------
1 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2e67a27..8a5cd5c 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -1,23 +1,20 @@
-CONFIG_EXPERIMENTAL=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_ARCH_MVEBU=y
CONFIG_MACH_ARMADA_370=y
-CONFIG_ARCH_SIRF=y
CONFIG_MACH_ARMADA_XP=y
CONFIG_ARCH_HIGHBANK=y
CONFIG_ARCH_SOCFPGA=y
-CONFIG_ARCH_SUNXI=y
-CONFIG_ARCH_WM8850=y
-# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
-CONFIG_ARCH_ZYNQ=y
-CONFIG_ARM_ERRATA_754322=y
CONFIG_PLAT_SPEAR=y
CONFIG_ARCH_SPEAR13XX=y
CONFIG_MACH_SPEAR1310=y
CONFIG_MACH_SPEAR1340=y
+CONFIG_ARCH_STIXXXX=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_SIRF=y
+CONFIG_ARCH_WM8850=y
+CONFIG_ARCH_ZYNQ=y
CONFIG_SMP=y
-CONFIG_ARM_ARCH_TIMER=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_HIGHPTE=y
@@ -25,27 +22,30 @@ CONFIG_ARM_APPENDED_DTB=y
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_NET=y
+CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_SD=y
CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_SATA_HIGHBANK=y
CONFIG_SATA_MV=y
-CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_NETDEVICES=y
CONFIG_NET_CALXEDA_XGMAC=y
CONFIG_SMSC911X=y
CONFIG_STMMAC_ETH=y
+CONFIG_KEYBOARD_SPEAR=y
CONFIG_SERIO_AMBAKMI=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_DW=y
-CONFIG_KEYBOARD_SPEAR=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_SIRFSOC=y
CONFIG_SERIAL_SIRFSOC_CONSOLE=y
CONFIG_SERIAL_VT8500=y
CONFIG_SERIAL_VT8500_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_ST_ASC=y
+CONFIG_SERIAL_ST_ASC_CONSOLE=y
CONFIG_IPMI_HANDLER=y
CONFIG_IPMI_SI=y
CONFIG_I2C=y
@@ -54,7 +54,6 @@ CONFIG_I2C_SIRF=y
CONFIG_SPI=y
CONFIG_SPI_PL022=y
CONFIG_SPI_SIRF=y
-CONFIG_GPIO_PL061=y
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
CONFIG_FB_WM8505=y
@@ -67,7 +66,6 @@ CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_SPEAR=y
-CONFIG_MMC_WMT=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_EDAC_HIGHBANK_MC=y
@@ -75,9 +73,9 @@ CONFIG_EDAC_HIGHBANK_L2=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_VT8500=y
-CONFIG_PWM=y
-CONFIG_PWM_VT8500=y
CONFIG_DMADEVICES=y
-CONFIG_PL330_DMA=y
-CONFIG_SIRF_DMA=y
CONFIG_DW_DMAC=y
+CONFIG_SIRF_DMA=y
+CONFIG_PL330_DMA=y
+CONFIG_PWM=y
+CONFIG_PWM_VT8500=y
--
1.7.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Mark Rutland
2013-06-10 10:40:32 UTC
Permalink
Post by Srinivas KANDAGATLA
This patch adds stih415 and stih416 support to multi_v7_defconfig.
This seems to drop a few options also:

CONFIG_ARM_ARCH_TIMER
CONFIG_ARM_ERRATA_754322
CONFIG_EXPERIMENTAL
CONFIG_GPIO_PL061
CONFIG_MMC_WMT

I just applied this to v3.10-rc5, and ran `make ARCH=arm multi_v7_defconfig`.
It seems MMC_WMT and GPIO_PL061 get selected elsewhere, but ARM_ARCH_TIMER and
ARM_ERRATA_754322 are left unselected.

Thanks,
Mark.
Post by Srinivas KANDAGATLA
---
arch/arm/configs/multi_v7_defconfig | 32 +++++++++++++++-----------------
1 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2e67a27..8a5cd5c 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -1,23 +1,20 @@
-CONFIG_EXPERIMENTAL=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_ARCH_MVEBU=y
CONFIG_MACH_ARMADA_370=y
-CONFIG_ARCH_SIRF=y
CONFIG_MACH_ARMADA_XP=y
CONFIG_ARCH_HIGHBANK=y
CONFIG_ARCH_SOCFPGA=y
-CONFIG_ARCH_SUNXI=y
-CONFIG_ARCH_WM8850=y
-# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
-CONFIG_ARCH_ZYNQ=y
-CONFIG_ARM_ERRATA_754322=y
CONFIG_PLAT_SPEAR=y
CONFIG_ARCH_SPEAR13XX=y
CONFIG_MACH_SPEAR1310=y
CONFIG_MACH_SPEAR1340=y
+CONFIG_ARCH_STIXXXX=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_SIRF=y
+CONFIG_ARCH_WM8850=y
+CONFIG_ARCH_ZYNQ=y
CONFIG_SMP=y
-CONFIG_ARM_ARCH_TIMER=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_HIGHPTE=y
@@ -25,27 +22,30 @@ CONFIG_ARM_APPENDED_DTB=y
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_NET=y
+CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_SD=y
CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_SATA_HIGHBANK=y
CONFIG_SATA_MV=y
-CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_NETDEVICES=y
CONFIG_NET_CALXEDA_XGMAC=y
CONFIG_SMSC911X=y
CONFIG_STMMAC_ETH=y
+CONFIG_KEYBOARD_SPEAR=y
CONFIG_SERIO_AMBAKMI=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_DW=y
-CONFIG_KEYBOARD_SPEAR=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_SIRFSOC=y
CONFIG_SERIAL_SIRFSOC_CONSOLE=y
CONFIG_SERIAL_VT8500=y
CONFIG_SERIAL_VT8500_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_ST_ASC=y
+CONFIG_SERIAL_ST_ASC_CONSOLE=y
CONFIG_IPMI_HANDLER=y
CONFIG_IPMI_SI=y
CONFIG_I2C=y
@@ -54,7 +54,6 @@ CONFIG_I2C_SIRF=y
CONFIG_SPI=y
CONFIG_SPI_PL022=y
CONFIG_SPI_SIRF=y
-CONFIG_GPIO_PL061=y
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
CONFIG_FB_WM8505=y
@@ -67,7 +66,6 @@ CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_SPEAR=y
-CONFIG_MMC_WMT=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_EDAC_HIGHBANK_MC=y
@@ -75,9 +73,9 @@ CONFIG_EDAC_HIGHBANK_L2=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_VT8500=y
-CONFIG_PWM=y
-CONFIG_PWM_VT8500=y
CONFIG_DMADEVICES=y
-CONFIG_PL330_DMA=y
-CONFIG_SIRF_DMA=y
CONFIG_DW_DMAC=y
+CONFIG_SIRF_DMA=y
+CONFIG_PL330_DMA=y
+CONFIG_PWM=y
+CONFIG_PWM_VT8500=y
--
1.7.6.5
_______________________________________________
devicetree-discuss mailing list
https://lists.ozlabs.org/listinfo/devicetree-discuss
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-10 10:58:38 UTC
Permalink
Thanks for testing...
Post by Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This patch adds stih415 and stih416 support to multi_v7_defconfig.
CONFIG_ARM_ARCH_TIMER
CONFIG_ARM_ERRATA_754322
ARM_ERRATA_754322 gets selected by the mach level Kconfig of stixxxx, so
it disappears, Should the mach level Kconfig select that?
Post by Srinivas KANDAGATLA
CONFIG_EXPERIMENTAL
CONFIG_GPIO_PL061
CONFIG_MMC_WMT
Comment 2: Without any modifications to multi_v7_defconfig if I run
savedefconfig CONFIG_ARM_ARCH_TIMER, CONFIG_EXPERIMENTAL,
CONFIG_GPIO_PL061 and CONFIG_MMC_WMT disappears.
Which suggests that these options seems to be selected by another
kconfigs or mach level. And since then the multi_v7_defconfig was not
run with savedefconfig.


Thanks,
srini
Post by Srinivas KANDAGATLA
I just applied this to v3.10-rc5, and ran `make ARCH=arm multi_v7_defconfig`.
It seems MMC_WMT and GPIO_PL061 get selected elsewhere, but ARM_ARCH_TIMER and
ARM_ERRATA_754322 are left unselected.
Thanks,
Mark.
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Mark Rutland
2013-06-10 13:15:13 UTC
Permalink
Post by Srinivas KANDAGATLA
Thanks for testing...
Post by Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
This patch adds stih415 and stih416 support to multi_v7_defconfig.
CONFIG_ARM_ARCH_TIMER
CONFIG_ARM_ERRATA_754322
ARM_ERRATA_754322 gets selected by the mach level Kconfig of stixxxx, so
it disappears, Should the mach level Kconfig select that?
I couldn't find the patch adding mach-stixxxx's Kconfig, though I seem to be
missing patch 6 of the series. As long as CONFIG_ARM_ERRATA_754322 appears in
the resulting .config, it should be fine.
Post by Srinivas KANDAGATLA
Post by Srinivas KANDAGATLA
CONFIG_EXPERIMENTAL
CONFIG_GPIO_PL061
CONFIG_MMC_WMT
Comment 2: Without any modifications to multi_v7_defconfig if I run
savedefconfig CONFIG_ARM_ARCH_TIMER, CONFIG_EXPERIMENTAL,
CONFIG_GPIO_PL061 and CONFIG_MMC_WMT disappears.
Which suggests that these options seems to be selected by another
kconfigs or mach level. And since then the multi_v7_defconfig was not
run with savedefconfig.
CONFIG_EXPERIMENTAL's gone as of 3d374d09f1: "final removal of
CONFIG_EXPERIMENTAL", so that's fine to go. CONFIG_GPIO_PL061 and
CONFIG_MMC_WMT get selected elsewhere, so that's fine.

It looks like the architected timer deselection is fallout of my own making,
the multi_v7_defconfig should now contain HAVE_ARM_ARCH_TIMER rather than
ARM_ARCH_TIMER.

Thanks,
Mark.
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-13 09:24:45 UTC
Permalink
Post by Mark Rutland
CONFIG_EXPERIMENTAL's gone as of 3d374d09f1: "final removal of
CONFIG_EXPERIMENTAL", so that's fine to go. CONFIG_GPIO_PL061 and
CONFIG_MMC_WMT get selected elsewhere, so that's fine.
Am planning to send a patch to clean this up, so that any new platform
addition to the multi_v7_defconfig will not under go this discussion again..
Post by Mark Rutland
It looks like the architected timer deselection is fallout of my own making,
the multi_v7_defconfig should now contain HAVE_ARM_ARCH_TIMER rather than
ARM_ARCH_TIMER.
Why should it even contain HAVE_ARM_ARCH_TIMER/ARM_ARCH_TIMER?
The only reason I see for de-selection is because none of the platforms
in the multi_v7 defconfig selects it.

Looks like there is no platform in mulit_v7 config which requires this
support. If there is one I think it should select it.

Am I correct?

Thanks,
srini

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Mark Rutland
2013-06-17 09:32:48 UTC
Permalink
Post by Srinivas KANDAGATLA
Post by Mark Rutland
CONFIG_EXPERIMENTAL's gone as of 3d374d09f1: "final removal of
CONFIG_EXPERIMENTAL", so that's fine to go. CONFIG_GPIO_PL061 and
CONFIG_MMC_WMT get selected elsewhere, so that's fine.
Am planning to send a patch to clean this up, so that any new platform
addition to the multi_v7_defconfig will not under go this discussion again..
Post by Mark Rutland
It looks like the architected timer deselection is fallout of my own making,
the multi_v7_defconfig should now contain HAVE_ARM_ARCH_TIMER rather than
ARM_ARCH_TIMER.
Why should it even contain HAVE_ARM_ARCH_TIMER/ARM_ARCH_TIMER?
The only reason I see for de-selection is because none of the platforms
in the multi_v7 defconfig selects it.
Looks like there is no platform in mulit_v7 config which requires this
support. If there is one I think it should select it.
Am I correct?
You're right, I agree that the selection should be moved down into the
platforms requiring it. I'll put together patches to fix up those platforms.

Thanks,
Mark.
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-10 09:28:10 UTC
Permalink
B2000 board is reference board for STIH415/416 SOCs, it has
2 x UART, 4x USB, 2 x Ethernet, 1 x SATA, 1 x PCIe, and 1GB RAM.

This patch add initial support to b2000 with STiH415/416 with UART2 as
console and a heard beat LED.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-***@public.gmane.org>
CC: Stephen Gallimore <stephen.gallimore-***@public.gmane.org>
CC: Arnd Bergmann <arnd-***@public.gmane.org>
---
arch/arm/boot/dts/Makefile | 2 +
arch/arm/boot/dts/stih415-b2000.dts | 15 ++++++++++++
arch/arm/boot/dts/stih416-b2000.dts | 16 +++++++++++++
arch/arm/boot/dts/stih41x-b2000.dtsi | 41 ++++++++++++++++++++++++++++++++++
4 files changed, 74 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/boot/dts/stih415-b2000.dts
create mode 100644 arch/arm/boot/dts/stih416-b2000.dts
create mode 100644 arch/arm/boot/dts/stih41x-b2000.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index f0895c5..d4615fd 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -177,6 +177,8 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
spear320-evb.dtb \
spear320-hmi.dtb
dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
+dtb-$(CONFIG_ARCH_STIXXXX)+= stih415-b2000.dtb \
+ stih416-b2000.dtb
dtb-$(CONFIG_ARCH_SUNXI) += \
sun4i-a10-cubieboard.dtb \
sun4i-a10-mini-xplus.dtb \
diff --git a/arch/arm/boot/dts/stih415-b2000.dts b/arch/arm/boot/dts/stih415-b2000.dts
new file mode 100644
index 0000000..d4af531
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-b2000.dts
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla-***@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih415.dtsi"
+#include "stih41x-b2000.dtsi"
+/ {
+ model = "STiH415 B2000 Board";
+ compatible = "st,stih415", "st,stih415-b2000";
+};
diff --git a/arch/arm/boot/dts/stih416-b2000.dts b/arch/arm/boot/dts/stih416-b2000.dts
new file mode 100644
index 0000000..a5eb6ee
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-b2000.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla-***@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih416.dtsi"
+#include "stih41x-b2000.dtsi"
+
+/ {
+ compatible = "st,stih416", "st,stih416-b2000";
+ model = "STiH416 B2000";
+};
diff --git a/arch/arm/boot/dts/stih41x-b2000.dtsi b/arch/arm/boot/dts/stih41x-b2000.dtsi
new file mode 100644
index 0000000..8e694d2
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x-b2000.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla-***@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/ {
+
+ memory{
+ device_type = "memory";
+ reg = <0x60000000 0x40000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyAS0,115200";
+ linux,stdout-path = &serial2;
+ };
+
+ aliases {
+ ttyAS0 = &serial2;
+ };
+
+ soc {
+ serial2: ***@fed32000 {
+ status = "okay";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ fp_led {
+ #gpio-cells = <1>;
+ label = "Front Panel LED";
+ gpios = <&PIO105 7>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ };
+};
--
1.7.6.5
Srinivas KANDAGATLA
2013-06-10 09:28:28 UTC
Permalink
B2020 ADI board is reference board for STIH415/416 SOCs, it has 2 x
UART, 4x USB, 1 x Ethernet, 1 x SATA, 1 x PCIe, and 2GB RAM with
standard set-top box IPs.

This patch adds initial support to B2020 with STiH415/416 with SBC_UART1
as console and a heard beat LED.

Signed-off-by: Srinivas Kandagatla <***@st.com>
CC: Stephen Gallimore <***@st.com>
CC: Stuart Menefy <***@st.com>
CC: Arnd Bergmann <***@arndb.de>
---
arch/arm/boot/dts/Makefile | 4 ++-
arch/arm/boot/dts/stih415-b2020.dts | 15 ++++++++++++
arch/arm/boot/dts/stih416-b2020.dts | 16 +++++++++++++
arch/arm/boot/dts/stih41x-b2020.dtsi | 42 ++++++++++++++++++++++++++++++++++
4 files changed, 76 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/boot/dts/stih415-b2020.dts
create mode 100644 arch/arm/boot/dts/stih416-b2020.dts
create mode 100644 arch/arm/boot/dts/stih41x-b2020.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d4615fd..0d24c95 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -178,7 +178,9 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
spear320-hmi.dtb
dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
dtb-$(CONFIG_ARCH_STIXXXX)+= stih415-b2000.dtb \
- stih416-b2000.dtb
+ stih416-b2000.dtb \
+ stih415-b2020.dtb \
+ stih416-b2020.dtb
dtb-$(CONFIG_ARCH_SUNXI) += \
sun4i-a10-cubieboard.dtb \
sun4i-a10-mini-xplus.dtb \
diff --git a/arch/arm/boot/dts/stih415-b2020.dts b/arch/arm/boot/dts/stih415-b2020.dts
new file mode 100644
index 0000000..442b019
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-b2020.dts
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <***@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih415.dtsi"
+#include "stih41x-b2020.dtsi"
+/ {
+ model = "STiH415 B2020 Board";
+ compatible = "st,stih415", "st,stih415-b2020";
+};
diff --git a/arch/arm/boot/dts/stih416-b2020.dts b/arch/arm/boot/dts/stih416-b2020.dts
new file mode 100644
index 0000000..276f28d
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-b2020.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <***@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih416.dtsi"
+#include "stih41x-b2020.dtsi"
+/ {
+ model = "STiH416 B2020";
+ compatible = "st,stih416", "st,stih416-b2020";
+
+};
diff --git a/arch/arm/boot/dts/stih41x-b2020.dtsi b/arch/arm/boot/dts/stih41x-b2020.dtsi
new file mode 100644
index 0000000..133e181
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x-b2020.dtsi
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <***@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+/ {
+ memory{
+ device_type = "memory";
+ reg = <0x40000000 0x80000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyAS0,115200";
+ linux,stdout-path = &sbc_serial1;
+ };
+
+ aliases {
+ ttyAS0 = &sbc_serial1;
+ };
+ soc {
+ sbc_serial1: ***@fe531000 {
+ status = "okay";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ red {
+ #gpio-cells = <1>;
+ label = "Front Panel LED";
+ gpios = <&PIO4 1>;
+ linux,default-trigger = "heartbeat";
+ };
+ green {
+ gpios = <&PIO4 7>;
+ default-state = "off";
+ };
+ };
+ };
+};
--
1.7.6.5
Srinivas KANDAGATLA
2013-06-10 09:27:05 UTC
Permalink
The STiH416 is advanced HD AVC processor with 3D graphics acceleration
and 1.2-GHz ARM Cortex-A9 SMP CPU.

Signed-off-by: Srinivas Kandagatla <***@st.com>
CC: Stephen Gallimore <***@st.com>
CC: Stuart Menefy <***@st.com>
CC: Arnd Bergmann <***@arndb.de>
CC: Linus Walleij <***@linaro.org>
---
Documentation/arm/stixxxx/stih416-overview.txt | 12 +
arch/arm/boot/dts/stih416-clock.dtsi | 41 +++
arch/arm/boot/dts/stih416-pinctrl.dtsi | 377 ++++++++++++++++=
++++++++
arch/arm/boot/dts/stih416.dtsi | 111 +++++++
arch/arm/mach-stixxxx/board-dt.c | 3 +-
5 files changed, 543 insertions(+), 1 deletions(-)
create mode 100644 Documentation/arm/stixxxx/stih416-overview.txt
create mode 100644 arch/arm/boot/dts/stih416-clock.dtsi
create mode 100644 arch/arm/boot/dts/stih416-pinctrl.dtsi
create mode 100644 arch/arm/boot/dts/stih416.dtsi

diff --git a/Documentation/arm/stixxxx/stih416-overview.txt b/Documenta=
tion/arm/stixxxx/stih416-overview.txt
new file mode 100644
index 0000000..e060867
--- /dev/null
+++ b/Documentation/arm/stixxxx/stih416-overview.txt
@@ -0,0 +1,12 @@
+ STiH416 Overview
+ =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+
+Introduction
+------------
+
+ The STiH416 is the next generation of HD, AVC set-top box processo=
rs
+ for satellite, cable, terrestrial and IP-STB markets.
+
+ Features
+ - ARM Cortex-A9 1.2 GHz dual core CPU
+ - SATA2=C3=972,USB 2.0=C3=973, PCIe, Gbit Ethernet MAC=C3=972
diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/s=
tih416-clock.dtsi
new file mode 100644
index 0000000..7026bf1
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics R&D Limited
+ * <stlinux-***@stlinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modif=
y
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/ {
+ clocks {
+ /*
+ * Fixed 30MHz oscillator inputs to SoC
+ */
+ CLK_SYSIN: CLK_SYSIN {
+ #clock-cells =3D <0>;
+ compatible =3D "fixed-clock";
+ clock-frequency =3D <30000000>;
+ clock-output-names =3D "CLK_SYSIN";
+ };
+
+ /*
+ * ARM Peripheral clock for timers
+ */
+ arm_periph_clk: arm_periph_clk {
+ #clock-cells =3D <0>;
+ compatible =3D "fixed-clock";
+ clock-frequency =3D <600000000>;
+ };
+
+ /*
+ * Bootloader initialized system infrastructure clock for
+ * serial devices.
+ */
+ CLK_S_ICN_REG_0: ***@4 {
+ #clock-cells =3D <0>;
+ compatible =3D "fixed-clock";
+ clock-frequency =3D <100000000>;
+ clock-output-names =3D "CLK_S_ICN_REG_0";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/stih416-pinctrl.dtsi b/arch/arm/boot/dts=
/stih416-pinctrl.dtsi
new file mode 100644
index 0000000..15843a9
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-pinctrl.dtsi
@@ -0,0 +1,377 @@
+
+/*
+ * Copyright (C) 2013 STMicroelectronics Limited.
+ * Author: Srinivas Kandagatla <***@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modif=
y
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+#include "stixxxx-pincfg.h"
+/ {
+
+ aliases {
+ gpio0 =3D &PIO0;
+ gpio1 =3D &PIO1;
+ gpio2 =3D &PIO2;
+ gpio3 =3D &PIO3;
+ gpio4 =3D &PIO4;
+ gpio5 =3D &PIO40;
+ gpio6 =3D &PIO5;
+ gpio7 =3D &PIO6;
+ gpio8 =3D &PIO7;
+ gpio9 =3D &PIO8;
+ gpio10 =3D &PIO9;
+ gpio11 =3D &PIO10;
+ gpio12 =3D &PIO11;
+ gpio13 =3D &PIO12;
+ gpio14 =3D &PIO30;
+ gpio15 =3D &PIO31;
+ gpio16 =3D &PIO13;
+ gpio17 =3D &PIO14;
+ gpio18 =3D &PIO15;
+ gpio19 =3D &PIO16;
+ gpio20 =3D &PIO17;
+ gpio21 =3D &PIO18;
+ gpio22 =3D &PIO100;
+ gpio23 =3D &PIO101;
+ gpio24 =3D &PIO102;
+ gpio25 =3D &PIO103;
+ gpio26 =3D &PIO104;
+ gpio27 =3D &PIO105;
+ gpio28 =3D &PIO106;
+ gpio29 =3D &PIO107;
+ };
+
+ soc {
+ pin-controller-sbc {
+ #address-cells =3D <1>;
+ #size-cells =3D <1>;
+ compatible =3D "st,stih416-pinctrl", "simple-bus";
+ st,retime-in-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 2250=
2500 2750 3000 3250>;
+ st,retime-out-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 225=
0 2500 2750 3000 3250>;
+ st,syscfg =3D <&syscfg_sbc>;
+ st,syscfg-offsets =3D <0 40 50 60 100>;
+ ranges;
+ PIO0: ***@fe610000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe610000 0x100>;
+ st,bank-name =3D "PIO0";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO1: ***@fe611000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe611000 0x100>;
+ st,bank-name =3D "PIO1";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO2: ***@fe612000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe612000 0x100>;
+ st,bank-name =3D "PIO2";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO3: ***@fe613000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe613000 0x100>;
+ st,bank-name =3D "PIO3";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO4: ***@fe614000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe614000 0x100>;
+ st,bank-name =3D "PIO4";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO40: ***@fe615000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe615000 0x100>;
+ st,bank-name =3D "PIO40";
+ st,retime-pin-mask =3D <0x7f>;
+ };
+
+ sbc_serial1 {
+ pinctrl_sbc_serial1: sbc_serial1 {
+ st,function =3D <ALT3>;
+ st,pins {
+ tx =3D <&PIO2 6 OUT>;
+ rx =3D <&PIO2 7 IN>;
+ };
+ };
+ };
+ };
+
+ pin-controller-front {
+ #address-cells =3D <1>;
+ #size-cells =3D <1>;
+ compatible =3D "st,stih416-pinctrl", "simple-bus";
+ st,retime-in-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 2250=
2500 2750 3000 3250>;
+ st,retime-out-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 225=
0 2500 2750 3000 3250>;
+ st,syscfg =3D <&syscfg_front>;
+ st,syscfg-offsets =3D <0 40 50 60 100>;
+ ranges;
+
+ PIO5: ***@fee00000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee00000 0x100>;
+ st,bank-name =3D "PIO5";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO6: ***@fee01000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee01000 0x100>;
+ st,bank-name =3D "PIO6";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO7: ***@fee02000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee02000 0x100>;
+ st,bank-name =3D "PIO7";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO8: ***@fee03000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee03000 0x100>;
+ st,bank-name =3D "PIO8";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO9: ***@fee04000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee04000 0x100>;
+ st,bank-name =3D "PIO9";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO10: ***@fee05000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee05000 0x100>;
+ st,bank-name =3D "PIO10";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO11: ***@fee06000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee06000 0x100>;
+ st,bank-name =3D "PIO11";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO12: ***@fee07000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee07000 0x100>;
+ st,bank-name =3D "PIO12";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO30: ***@fee08000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee08000 0x100>;
+ st,bank-name =3D "PIO30";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO31: ***@fee09000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfee09000 0x100>;
+ st,bank-name =3D "PIO31";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ };
+
+ pin-controller-rear {
+ #address-cells =3D <1>;
+ #size-cells =3D <1>;
+ compatible =3D "st,stih416-pinctrl", "simple-bus";
+ st,retime-in-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 2250=
2500 2750 3000 3250>;
+ st,retime-out-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 225=
0 2500 2750 3000 3250>;
+ st,syscfg =3D <&syscfg_rear>;
+ st,syscfg-offsets =3D <0 40 50 60 100>;
+ ranges;
+
+ PIO13: ***@fe820000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe820000 0x100>;
+ st,bank-name =3D "PIO13";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO14: ***@fe821000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe821000 0x100>;
+ st,bank-name =3D "PIO14";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO15: ***@fe822000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe822000 0x100>;
+ st,bank-name =3D "PIO15";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO16: ***@fe823000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe823000 0x100>;
+ st,bank-name =3D "PIO16";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO17: ***@fe824000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe824000 0x100>;
+ st,bank-name =3D "PIO17";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO18: ***@fe825000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfe825000 0x100>;
+ st,bank-name =3D "PIO18";
+ st,retime-pin-mask =3D <0xf>;
+ };
+
+ serial2 {
+ pinctrl_serial2: serial2-0 {
+ st,function =3D <ALT2>;
+ st,pins {
+ tx =3D <&PIO17 4 OUT>;
+ rx =3D <&PIO17 5 IN>;
+ output-enable =3D <&PIO11 3 OUT>;
+ };
+ };
+ };
+ };
+
+ pin-controller-fvdp-fe {
+ #address-cells =3D <1>;
+ #size-cells =3D <1>;
+ compatible =3D "st,stih416-pinctrl", "simple-bus";
+ st,retime-in-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 2250=
2500 2750 3000 3250>;
+ st,retime-out-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 225=
0 2500 2750 3000 3250>;
+ st,syscfg =3D <&syscfg_fvdp_fe>;
+ st,syscfg-offsets =3D <0 40 50 60 100>;
+ ranges;
+
+ PIO100: ***@fd6b0000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfd6b0000 0x100>;
+ st,bank-name =3D "PIO100";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO101: ***@fd6b1000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfd6b1000 0x100>;
+ st,bank-name =3D "PIO101";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO102: ***@fd6b2000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfd6b2000 0x100>;
+ st,bank-name =3D "PIO102";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ };
+
+ pin-controller-fvdp-lite {
+ #address-cells =3D <1>;
+ #size-cells =3D <1>;
+ compatible =3D "st,stih416-pinctrl", "simple-bus";
+ st,retime-in-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 2250=
2500 2750 3000 3250>;
+ st,retime-out-delay =3D <0 300 500 750 1000 1250 1500 1750 2000 225=
0 2500 2750 3000 3250>;
+ st,syscfg =3D <&syscfg_fvdp_lite>;
+ st,syscfg-offsets =3D <0 40 50 60 100>;
+ ranges;
+
+ PIO103: ***@fd330000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfd330000 0x100>;
+ st,bank-name =3D "PIO103";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO104: ***@fd331000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfd331000 0x100>;
+ st,bank-name =3D "PIO104";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO105: ***@fd332000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfd332000 0x100>;
+ st,bank-name =3D "PIO105";
+ st,retime-pin-mask =3D <0xff>;
+ };
+ PIO106: ***@fd333000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfd333000 0x100>;
+ st,bank-name =3D "PIO106";
+ st,retime-pin-mask =3D <0xff>;
+ };
+
+ PIO107: ***@fd334000 {
+ #gpio-cells =3D <1>;
+ compatible =3D "st,stixxxx-gpio";
+ gpio-controller;
+ reg =3D <0xfd334000 0x100>;
+ st,bank-name =3D "PIO107";
+ st,retime-pin-mask =3D <0xf>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416=
=2Edtsi
new file mode 100644
index 0000000..7dbe450
--- /dev/null
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 STMicroelectronics Limited.
+ * Author: Srinivas Kandagatla <***@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modif=
y
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+#include "stih41x.dtsi"
+#include "stih416-clock.dtsi"
+#include "stih416-pinctrl.dtsi"
+/ {
+ L2: cache-controller {
+ compatible =3D "arm,pl310-cache";
+ reg =3D <0xfffe2000 0x1000>;
+ arm,data-latency =3D <3 3 3>;
+ arm,tag-latency =3D <2 2 2>;
+ cache-unified;
+ cache-level =3D <2>;
+ };
+
+ soc {
+ #address-cells =3D <1>;
+ #size-cells =3D <1>;
+ interrupt-parent =3D <&intc>;
+ ranges;
+ compatible =3D "simple-bus";
+
+ syscfg_sbc:***@fe600000{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfe600000 0x1000>;
+ syscfg-range =3D <0 999>;
+ syscfg-name =3D "SYSCFG_SBC";
+ };
+ syscfg_front:***@fee10000{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfee10000 0x1000>;
+ syscfg-range =3D <1000 999>;
+ syscfg-name =3D "SYSCFG_FRONT";
+ };
+ syscfg_rear:***@fe830000{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfe830000 0x1000>;
+ syscfg-range =3D <2000 999>;
+ syscfg-name =3D "SYSCFG_REAR";
+ };
+
+ /* MPE */
+ syscfg_fvdp_fe:***@fddf0000{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfddf0000 0x1000>;
+ syscfg-range =3D <5000 999>;
+ syscfg-name =3D "SYSCFG_FVDP_FE";
+ };
+ syscfg_fvdp_lite:***@fd6a0000{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfd6a0000 0x1000>;
+ syscfg-range =3D <6000 999>;
+ syscfg-name =3D "SYSCFG_FVDP_LITE";
+ };
+
+ syscfg_cpu:***@fdde0000{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfdde0000 0x1000>;
+ syscfg-range =3D <7000 999>;
+ syscfg-name =3D "SYSCFG_CPU";
+ };
+
+ syscfg_compo:***@fd320000{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfd320000 0x1000>;
+ syscfg-range =3D <8000 999>;
+ syscfg-name =3D "SYSCFG_COMPO";
+ };
+
+ syscfg_transport:***@fd690000{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfd690000 0x1000>;
+ syscfg-range =3D <9000 999>;
+ syscfg-name =3D "SYSCFG_TRANSPORT";
+ };
+
+ syscfg_lpm:***@fe4b5100{
+ compatible =3D "st,stih416-syscfg";
+ reg =3D <0xfe4b5100 0x8>;
+ syscfg-range =3D <0 10>;
+ syscfg-name =3D "LPM_CFG_REGS";
+ };
+
+ serial2: ***@fed32000{
+ compatible =3D "st,asc";
+ status =3D "disabled";
+ reg =3D <0xfed32000 0x2c>;
+ interrupts =3D <0 197 0>;
+ clocks =3D <&CLK_S_ICN_REG_0>;
+ pinctrl-names =3D "default";
+ pinctrl-0 =3D <&pinctrl_serial2>;
+ };
+
+ /* SBC_UART1 */
+ sbc_serial1: ***@fe531000 {
+ compatible =3D "st,asc";
+ status =3D "disabled";
+ reg =3D <0xfe531000 0x2c>;
+ interrupts =3D <0 210 0>;
+ pinctrl-names =3D "default";
+ pinctrl-0 =3D <&pinctrl_sbc_serial1>;
+ clocks =3D <&CLK_SYSIN>;
+ };
+ };
+};
diff --git a/arch/arm/mach-stixxxx/board-dt.c b/arch/arm/mach-stixxxx/b=
oard-dt.c
index 52ce665..2b2552e 100644
--- a/arch/arm/mach-stixxxx/board-dt.c
+++ b/arch/arm/mach-stixxxx/board-dt.c
@@ -37,10 +37,11 @@ static void __init stih41x_timer_init(void)
=20
static const char *stih41x_dt_match[] __initdata =3D {
"st,stih415",
+ "st,stih416",
NULL
};
=20
-DT_MACHINE_START(STM, "STiH415 SoC with Flattened Device Tree")
+DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree")
.init_time =3D stih41x_timer_init,
.smp =3D smp_ops(stixxxx_smp_ops),
.dt_compat =3D stih41x_dt_match,
--=20
1.7.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Arnd Bergmann
2013-06-10 13:52:07 UTC
Permalink
Post by Srinivas KANDAGATLA
+ soc {
+ pin-controller-sbc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,stih416-pinctrl", "simple-bus";
Why is this both its own device with a compatible string and a
"simple-bus" at the same time? Wouldn't it be simpler to just
scan the child device nodes from the "st,stih416-pinctrl"
driver instead of having a separate platform_driver for them?
Post by Srinivas KANDAGATLA
+ st,retime-in-delay = <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+ st,retime-out-delay = <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+ st,syscfg = <&syscfg_sbc>;
+ st,syscfg-offsets = <0 40 50 60 100>;
+ ranges;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe610000 0x100>;
+ st,bank-name = "PIO0";
+ st,retime-pin-mask = <0xff>;
+ };
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe611000 0x100>;
+ st,bank-name = "PIO1";
+ st,retime-pin-mask = <0xff>;
+ };
What is in the ranges between these registers? It seems you have
256 bytes for each pinctrl node, with 4kb spacing. I wonder if
it would make sense to declare the entire range to belong to a single
pinctrl device. At least since all of the registers are in a single
range, you could add a property like

ranges = <0 0xfe610000 0x10000>;

and use relative addresses in the sub-nodes.

Please don't use identifiers with 'xxx' in them. Instead use numbers
of actual chips, ideally using the first one that this is compatible
with.
Post by Srinivas KANDAGATLA
+ compatible = "st,stih416-syscfg";
+ reg = <0xfe600000 0x1000>;
+ syscfg-range = <0 999>;
+ syscfg-name = "SYSCFG_SBC";
+ };
+ compatible = "st,stih416-syscfg";
+ reg = <0xfee10000 0x1000>;
+ syscfg-range = <1000 999>;
+ syscfg-name = "SYSCFG_FRONT";
+ };
Did you mean to declare ranges excluding 1000 and 2000 here?
Normally I would expect inclusive ranges like syscfg-range=<0 1000>;

What is the idea of the 'syscfg-name'? If the nodes are all different,
I would expect them to have distinct "compatible" values and not
need them.

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-10 16:17:53 UTC
Permalink
Thankyou for your comments.
Post by Arnd Bergmann
Post by Srinivas KANDAGATLA
+ soc {
+ pin-controller-sbc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,stih416-pinctrl", "simple-bus";
Why is this both its own device with a compatible string and a
"simple-bus" at the same time? Wouldn't it be simpler to just
scan the child device nodes from the "st,stih416-pinctrl"
driver instead of having a separate platform_driver for them?
Am happy to get rid of gpio platform_driver, But looking at the existing
pinctrl drivers like at91, they do it exactly like this.

Also having a gpio platform driver ties the resources to driver in a
neat way.
Post by Arnd Bergmann
Post by Srinivas KANDAGATLA
+ st,retime-in-delay = <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+ st,retime-out-delay = <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+ st,syscfg = <&syscfg_sbc>;
+ st,syscfg-offsets = <0 40 50 60 100>;
+ ranges;
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe610000 0x100>;
+ st,bank-name = "PIO0";
+ st,retime-pin-mask = <0xff>;
+ };
+ #gpio-cells = <1>;
+ compatible = "st,stixxxx-gpio";
+ gpio-controller;
+ reg = <0xfe611000 0x100>;
+ st,bank-name = "PIO1";
+ st,retime-pin-mask = <0xff>;
+ };
What is in the ranges between these registers? It seems you have
256 bytes for each pinctrl node, with 4kb spacing. I wonder if
it would make sense to declare the entire range to belong to a single
pinctrl device. At least since all of the registers are in a single
range, you could add a property like
ranges = <0 0xfe610000 0x10000>;
and use relative addresses in the sub-nodes.
OK, I will change to use ranges.
Post by Arnd Bergmann
Please don't use identifiers with 'xxx' in them. Instead use numbers
of actual chips, ideally using the first one that this is compatible
with.
Ok, I will change st,stixxxx-gpio to st,stih415-gpio.
Post by Arnd Bergmann
Post by Srinivas KANDAGATLA
+ compatible = "st,stih416-syscfg";
+ reg = <0xfe600000 0x1000>;
+ syscfg-range = <0 999>;
+ syscfg-name = "SYSCFG_SBC";
+ };
+ compatible = "st,stih416-syscfg";
+ reg = <0xfee10000 0x1000>;
+ syscfg-range = <1000 999>;
+ syscfg-name = "SYSCFG_FRONT";
+ };
Did you mean to declare ranges excluding 1000 and 2000 here?
Normally I would expect inclusive ranges like syscfg-range=<0 1000>;
These numbers are from data sheet so I used it as it is.
Post by Arnd Bergmann
What is the idea of the 'syscfg-name'? If the nodes are all different,
The idea of having syscfg-name is to lookup any sysconf bank(regmap)
from code which do not have reference to phandle from device trees.
Post by Arnd Bergmann
I would expect them to have distinct "compatible" values and not
need them.
Yes, If we have distinct compatible we would not need them, but there
will be 5-10 compatibility list for each SOC.
It looks like its going to be much neater Am going to try this change
and see how it looks like.
Post by Arnd Bergmann
Arnd
_______________________________________________
devicetree-discuss mailing list
https://lists.ozlabs.org/listinfo/devicetree-discuss
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Srinivas KANDAGATLA
2013-06-14 07:12:35 UTC
Permalink
Post by Arnd Bergmann
Post by Srinivas KANDAGATLA
+ soc {
+ pin-controller-sbc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,stih416-pinctrl", "simple-bus";
Why is this both its own device with a compatible string and a
"simple-bus" at the same time? Wouldn't it be simpler to just
scan the child device nodes from the "st,stih416-pinctrl"
driver instead of having a separate platform_driver for them?
I did try this suggestion, and it simplified driver too, I will do this
change in next version.

Thanks,
srini
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Linus Walleij
2013-06-19 18:34:52 UTC
Permalink
Post by Arnd Bergmann
+ soc {
+ pin-controller-sbc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,stih416-pinctrl", "simple-bus";
Why is this both its own device with a compatible string and a
"simple-bus" at the same time? Wouldn't it be simpler to just
scan the child device nodes from the "st,stih416-pinctrl"
driver instead of having a separate platform_driver for them?
I think that in my comments to the pinctrl driver I had some
similar comment, so it's probably a good idea to look into
this.

Yours,
Linus Walleij
Murali Karicheri
2014-10-29 20:28:15 UTC
Permalink
This patch enables PCI controller driver for Keystone SoCs by
default.

Signed-off-by: Murali Karicheri <m-***@ti.com>
CC: Santosh Shilimkar <***@kernel.org>
CC: Russell King <***@arm.linux.org.uk>
CC: Greg Kroah-Hartman <***@linuxfoundation.org>
---
v2 - Added a description in the commit log per comment
v1 - fixed email ID for Santosh
arch/arm/configs/keystone_defconfig | 3 +++
1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
index 932ae40..40d3e9d 100644
--- a/arch/arm/configs/keystone_defconfig
+++ b/arch/arm/configs/keystone_defconfig
@@ -20,6 +20,9 @@ CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_ARCH_KEYSTONE=y
CONFIG_ARM_LPAE=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_KEYSTONE=y
CONFIG_SMP=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
--
1.7.9.5
Murali Karicheri
2014-10-29 20:28:14 UTC
Permalink
Now that Keystone PCI controller is merged, add pcie related options
by default for keystone architecture so that driver can be enabled in
the build.

Signed-off-by: Murali Karicheri <m-***@ti.com>
CC: Russell King <***@arm.linux.org.uk>
CC: Santosh Shilimkar <***@kernel.org>
---
- V2 - No change w.r.t v1
- v1 - No change w.r.t initial version
arch/arm/mach-keystone/Kconfig | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
index 98a156a..ea955f6db 100644
--- a/arch/arm/mach-keystone/Kconfig
+++ b/arch/arm/mach-keystone/Kconfig
@@ -9,6 +9,8 @@ config ARCH_KEYSTONE
select COMMON_CLK_KEYSTONE
select ARCH_SUPPORTS_BIG_ENDIAN
select ZONE_DMA if ARM_LPAE
+ select MIGHT_HAVE_PCI
+ select PCI_DOMAINS if PCI
help
Support for boards based on the Texas Instruments Keystone family of
SoCs.
--
1.7.9.5
Murali Karicheri
2014-10-29 20:28:16 UTC
Permalink
Add common DT bindings to support PCI controller driver for port 0 on all
of the K2 SoCs that has Synopsis Designware based pcie h/w.

Signed-off-by: Murali Karicheri <m-***@ti.com>
CC: Santosh Shilimkar <***@kernel.org>
CC: Rob Herring <robh+***@kernel.org>
CC: Pawel Moll <***@arm.com>
CC: Mark Rutland <***@arm.com>
CC: Ian Campbell <ijc+***@hellion.org.uk>
CC: Kumar Gala <***@codeaurora.org>
CC: Russell King <***@arm.linux.org.uk>
CC: ***@vger.kernel.org
---
v2 - Minor editorial update based on comment
v1 - fixed email ID for Santosh and reworded the commit description a bit to
be consistent with the subject.
arch/arm/boot/dts/keystone.dtsi | 45 +++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)

diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index 5d3e83f..c06542b 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -285,5 +285,50 @@
#interrupt-cells = <1>;
ti,syscon-dev = <&devctrl 0x2a0>;
};
+
+ ***@21800000 {
+ compatible = "ti,keystone-pcie", "snps,dw-pcie";
+ clocks = <&clkpcie>;
+ clock-names = "pcie";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ reg = <0x21801000 0x2000>, <0x21800000 0x1000>, <0x02620128 4>;
+ ranges = <0x81000000 0 0 0x23250000 0 0x4000
+ 0x82000000 0 0x50000000 0x50000000 0 0x10000000>;
+
+ device_type = "pci";
+ num-lanes = <2>;
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc0 0>, /* INT A */
+ <0 0 0 2 &pcie_intc0 1>, /* INT B */
+ <0 0 0 3 &pcie_intc0 2>, /* INT C */
+ <0 0 0 4 &pcie_intc0 3>; /* INT D */
+
+ pcie_msi_intc0: msi-interrupt-controller {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 31 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 33 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>;
+ };
+
+ pcie_intc0: legacy-interrupt-controller {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 28 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 29 IRQ_TYPE_EDGE_RISING>;
+ };
+ };
};
};
--
1.7.9.5
Murali Karicheri
2014-10-29 20:28:17 UTC
Permalink
K2E SoC has a second PCI port based on Synopsis Designware PCIe h/w.
Add DT bindings to support PCI controller for port 1 for this SoC.

Signed-off-by: Murali Karicheri <m-***@ti.com>
CC: Santosh Shilimkar <***@kernel.org>
CC: Rob Herring <robh+***@kernel.org>
CC: Pawel Moll <***@arm.com>
CC: Mark Rutland <***@arm.com>
CC: Ian Campbell <ijc+***@hellion.org.uk>
CC: Kumar Gala <***@codeaurora.org>
CC: Russell King <***@arm.linux.org.uk>
CC: ***@vger.kernel.org
---
v2 - minor ediorial updates based on comments
v1 - fixed email ID for Santosh and reworded commit description to be
consistent with the subject.
arch/arm/boot/dts/k2e.dtsi | 45 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)

diff --git a/arch/arm/boot/dts/k2e.dtsi b/arch/arm/boot/dts/k2e.dtsi
index c358b4b..5fc14683 100644
--- a/arch/arm/boot/dts/k2e.dtsi
+++ b/arch/arm/boot/dts/k2e.dtsi
@@ -85,6 +85,51 @@
#gpio-cells = <2>;
gpio,syscon-dev = <&devctrl 0x240>;
};
+
+ ***@21020000 {
+ compatible = "ti,keystone-pcie","snps,dw-pcie";
+ clocks = <&clkpcie1>;
+ clock-names = "pcie";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ reg = <0x21021000 0x2000>, <0x21020000 0x1000>, <0x02620128 4>;
+ ranges = <0x81000000 0 0 0x23260000 0x4000 0x4000
+ 0x82000000 0 0x60000000 0x60000000 0 0x10000000>;
+
+ device_type = "pci";
+ num-lanes = <2>;
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc1 0>, /* INT A */
+ <0 0 0 2 &pcie_intc1 1>, /* INT B */
+ <0 0 0 3 &pcie_intc1 2>, /* INT C */
+ <0 0 0 4 &pcie_intc1 3>; /* INT D */
+
+ pcie_msi_intc1: msi-interrupt-controller {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 377 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 378 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 379 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 380 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 381 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 382 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 383 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 384 IRQ_TYPE_EDGE_RISING>;
+ };
+
+ pcie_intc1: legacy-interrupt-controller {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 374 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 375 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 376 IRQ_TYPE_EDGE_RISING>;
+ };
+ };
};
};
--
1.7.9.5
santosh shilimkar
2014-10-29 21:10:18 UTC
Permalink
v2: Some more minor edits based on comments
Thanks for quick update. I will queue these up as
mentioned.

Regards,
Santosh

Continue reading on narkive:
Loading...