Skip to contentSkip to conversation

AR7: 4th effort

PATCH In review Matteo Croce 10 participants 28 messages Sep 20, 2007 – Oct 7, 2007

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover AR7: 4th effort

These are patch for the AR7 router board:
core, serial hack, mtd partition map, ethernet, gpio pins, watchdog and leds

Here is a live session log:

ADAM2 Revision 0.22.12
(C) Copyright 1996-2003 Texas Instruments Inc. All Rights Reserved.
(C) Copyright 2003 Telogy Networks, Inc.
Usage: setmfreq [-d] [-s sys_freq, in MHz] [cpu_freq, in MHz] Memory optimization Complete!

mac_init(): Find mac [00:13:10:01:C5:2A] in location 1 Find mac [00:13:10:01:C5:2A] in location 1 mac_value:00:13:10:01:C5:2A
tftpserver initialized

Adam2_AR7WRD >
Press any key to abort OS load, or wait 5 seconds for OS to boot...
Linux version 2.6.22.4 (matteo@raver) (gcc version 4.2.1) #1 Thu Sep 20 16:41:39 CEST 2007 CPU revision is: 00018448
TI AR7 (TNETD7300), ID: 0x0005, Revision: 0x02
Determined physical RAM map:
memory: 01000000 @ 14000000 (usable)
Built 1 zonelists. Total pages: 4064
Kernel command line: init=/etc/preinit rootfstype=squashfs,jffs2, console=ttyS0,38400n8r Primary instruction cache 16kB, physically tagged, 4-way, linesize 16 bytes.
Primary data cache 16kB, 4-way, linesize 16 bytes.
Synthesized TLB refill handler (20 instructions).
Synthesized TLB load handler fastpath (32 instructions).
Synthesized TLB store handler fastpath (32 instructions).
Synthesized TLB modify handler fastpath (31 instructions).
PID hash table entries: 64 (order: 6, 256 bytes)
Using 75.000 MHz high precision timer.
Dentry cache hash table entries: 2048 (order: 1, 8192 bytes)
Inode-cache hash table entries: 1024 (order: 0, 4096 bytes)
Memory: 12228k/16384k available (2315k kernel code, 4156k reserved, 423k data, 112k init, 0k highmem)
SLUB: Genslabs=17, HWalign=32, Order=0-1, MinObjects=4, CPUs=1, Nodes=1
Mount-cache hash table entries: 512
NET: Registered protocol family 16
vlynq0: regs 0x08611800, irq 29, mem 0x04000000
vlynq1: regs 0x08611c00, irq 33, mem 0x0c000000
vlynq-pci: attaching device TI TNETW1130 at vlynq0
registering PCI controller with io_map_base unset
Generic PHY: Registered new driver
NET: Registered protocol family 8
NET: Registered protocol family 20
Time: MIPS clocksource has been installed.
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 512 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: -1, 2048 bytes)
TCP: Hash tables configured (established 512 bind 512)
TCP reno registered
squashfs: version 3.0 (2006/03/15) Phillip Lougher
Registering mini_fo version $Id$
JFFS2 version 2.2. (NAND) (SUMMARY) © 2001-2006 Red Hat, Inc.
io scheduler noop registered
io scheduler deadline registered (default)
ar7_wdt: timer margin 59 seconds (prescale 65535, change 57180, freq 62500000)
Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing disabled
serial8250: ttyS0 at MMIO 0x8610e00 (irq = 15) is a TI-AR7
console handover: boot [early0] -> real [ttyS0]
serial8250: ttyS1 at MMIO 0x8610f00 (irq = 16) is a TI-AR7
Fixed PHY: Registered new driver
PPP generic driver version 2.4.2
cpmac-mii: probed
cpmac: device eth0 (regs: 08612800, irq: 41, phy: fixed@100:1, mac: 00:13:10:01:c5:2a)
cpmac: device eth1 (regs: 08610000, irq: 27, phy: 0:1f, mac: 00:13:10:01:c5:2a) physmap platform flash device: 00800000 at 10000000
physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank
Amd/Fujitsu Extended Query Table at 0x0040
physmap-flash.0: Swapping erase regions for broken CFI table.
number of CFI chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
cmdlinepart partition parsing not available
RedBoot partition parsing not available
Parsing AR7 partition map...
4 ar7part partitions found on MTD device physmap-flash.0
Creating 4 MTD partitions on "physmap-flash.0":
0x00000000-0x00010000 : "loader"
0x003f0000-0x00400000 : "config"
0x00020000-0x003f0000 : "linux"
0x0010008e-0x003f0000 : "rootfs"
mtd: partition "rootfs" doesn't start on an erase block boundary -- force read-only
mtd: partition "rootfs" set to be root filesystem
mtd: partition "rootfs_data" created automatically, ofs=280000, len=170000 0x00280000-0x003f0000 : "rootfs_data"
Registered led device: ar7:status
u32 classifier
Actions configured
nf_conntrack version 0.5.0 (128 buckets, 1024 max)
ip_tables: (C) 2000-2006 Netfilter Core Team
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 10
IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
VFS: Mounted root (squashfs filesystem) readonly.
Freeing unused kernel memory: 112k freed
Warning: unable to open an initial console.
Algorithmics/MIPS FPU Emulator v1.5
mini_fo: using base directory: /
mini_fo: using storage directory: /tmp/root
init started: BusyBox v1.4.2 (2007-09-16 03:20:09 CEST) multi-call binary
PHY: fixed@100:1 - Link is Up - 10/Half
registered device TI Avalanche SAR
Sangam detected
requesting firmware image "ar0700xx.bin"
Creating new root folder avalanche in the proc for the driver stats
Texas Instruments ATM driver: version:[7.02.01.00]
jffs2_scan_eraseblock(): End of filesystem marker found at 0x0 jffs2_build_filesystem(): unlocking the mtd device... done.
jffs2_build_filesystem(): erasing all blocks after the end marker... done.
eth0: no IPv6 routers present
mini_fo: using base directory: /
mini_fo: using storage directory: /jffs
[/]# uname -a
Linux OpenWrt 2.6.22.4 #1 Thu Sep 20 16:41:39 CEST 2007 mips unknown
[/]# cat /proc/cpuinfo
system type : TI AR7 (TNETD7300)
processor : 0
cpu model : MIPS 4KEc V4.8
BogoMIPS : 149.50
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes

ASEs implemented        :
VCED exceptions         : not available
VCEI exceptions         : not available
#1 lore raw

PATCH 1/7 AR7: core support

Support for memory mapping, clock and the vlynq bus

arch/mips/Kconfig +16 -0
index 3b807b4..10a95eb 100644
@@ -15,6 +15,22 @@ choice
 	prompt "System type"
 	default SGI_IP22
 
+config AR7
+	bool "Texas Instruments AR7"
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_KGDB
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select GENERIC_GPIO
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+
 config MACH_ALCHEMY
 	bool "Alchemy processor based machines"
 
arch/mips/Makefile +7 -0
index 32c1c8f..3989a8b 100644
@@ -161,6 +161,13 @@ libs-$(CONFIG_SIBYTE_CFE)	+= arch/mips/sibyte/cfe/
 #
 
 #
+# Texas Instruments AR7
+#
+core-$(CONFIG_AR7)		+= arch/mips/ar7/
+cflags-$(CONFIG_AR7)		+= -Iinclude/asm-mips/ar7
+load-$(CONFIG_AR7)		+= 0xffffffff94100000
+
+#
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
 core-$(CONFIG_MACH_JAZZ)	+= arch/mips/jazz/
arch/mips/ar7/Makefile new file +14 -0
new file mode 100644
index 0000000..bd10957
@@ -0,0 +1,14 @@
+
+obj-y := \
+	prom.o \
+	setup.o \
+	memory.o \
+	irq.o \
+	time.o \
+	platform.o \
+	gpio.o \
+	clock.o \
+	vlynq.o
+
+obj-$(CONFIG_PCI) += \
+	vlynq-pci.o
arch/mips/ar7/clock.c new file +485 -0

485 lines not on this page · raw message

arch/mips/ar7/gpio.c new file +48 -0

48 lines not on this page · raw message

arch/mips/ar7/irq.c new file +182 -0

182 lines not on this page · raw message

arch/mips/ar7/memory.c new file +73 -0

73 lines not on this page · raw message

arch/mips/ar7/platform.c new file +418 -0

418 lines not on this page · raw message

arch/mips/ar7/prom.c new file +322 -0

322 lines not on this page · raw message

arch/mips/ar7/setup.c new file +106 -0

106 lines not on this page · raw message

arch/mips/ar7/time.c new file +32 -0
new file mode 100644
index 0000000..4be2895
@@ -0,0 +1,32 @@
+/*
+ * Carsten Langgaard, [email protected]
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <asm/time.h>
+#include <asm/ar7/ar7.h>
+
+void __init ar7_time_init(void)
+{
+	mips_hpt_frequency = ar7_cpu_freq() / 2;
+}
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+	setup_irq(7, irq);
+}
arch/mips/ar7/vlynq-pci.c new file +436 -0

436 lines not on this page · raw message

arch/mips/ar7/vlynq.c new file +653 -0

653 lines not on this page · raw message

arch/mips/kernel/traps.c +17 -5
index 6379003..577fc3d 100644
@@ -1074,11 +1074,23 @@ void *set_except_vector(int n, void *addr)
 	unsigned long old_handler = exception_handlers[n];
 
 	exception_handlers[n] = handler;
-	if (n == 0 && cpu_has_divec) {
-		*(volatile u32 *)(ebase + 0x200) = 0x08000000 |
-		                                 (0x03ffffff & (handler >> 2));
-		flush_icache_range(ebase + 0x200, ebase + 0x204);
-	}
+	if (n == 0 && cpu_has_divec)
+		if ((handler ^ (ebase + 4)) & 0xfc000000) {
+			/* lui k0, 0x0000 */
+			*(u32 *)(ebase + 0x200) = 0x3c1a0000 | (handler >> 16);
+			/* ori k0, 0x0000 */
+			*(u32 *)(ebase + 0x204) =
+					0x375a0000 | (handler & 0xffff);
+			/* jr k0 */
+			*(u32 *)(ebase + 0x208) = 0x03400008;
+			/* nop */
+			*(u32 *)(ebase + 0x20C) = 0x00000000;
+			flush_icache_range(ebase + 0x200, ebase + 0x210);
+		} else {
+			*(volatile u32 *)(ebase + 0x200) =
+				0x08000000 | (0x03ffffff & (handler >> 2));
+			flush_icache_range(ebase + 0x200, ebase + 0x204);
+		}
 	return (void *)old_handler;
 }
 
include/asm-mips/ar7/ar7.h new file +168 -0

168 lines not on this page · raw message

include/asm-mips/ar7/gpio.h new file +120 -0

120 lines not on this page · raw message

include/asm-mips/ar7/prom.h new file +25 -0
new file mode 100644
index 0000000..62d7d5c

Lines of this file are not shown. View the raw message.

include/asm-mips/ar7/spaces.h new file +32 -0
new file mode 100644
index 0000000..f4d1237

Lines of this file are not shown. View the raw message.

include/asm-mips/ar7/vlynq.h new file +109 -0

109 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.

#2 lore raw

Re: [PATCH][MIPS][1/7] AR7: core support

Forgot this:

include/asm-mips/page.h +4 -2
index e3301e5..73a59d1 100644
@@ -184,8 +184,10 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + UNCAC_BASE)
-#define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET)
+#define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + UNCAC_BASE +	\
+				 PHYS_OFFSET)
+#define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET -	\
+				 PHYS_OFFSET)
 
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
#3 lore raw

Re: [PATCH][MIPS][1/7] AR7: core support

In reply to Matteo Croce

include/asm-mips/ar7/gpio.h line 61

Quoted 7 lines · Matteo Croce
include/asm-mips/ar7/gpio.h new file +7 -0
+static inline int gpio_get_value(unsigned gpio)
+{
+	void __iomem *gpio_in =
+		(void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT);
+
+	if (gpio >= AR7_GPIO_MAX)
+		return -EINVAL;

Checking with AR7_GPIO_MAX can be dropped from gpio_set_value() and gpio_get_value(). The validity checking is done in gpio_direction_*().

--- excerpt from Documentation/gpio.txt ---
The get/set calls have no error returns because "invalid GPIO" should have been reported earlier from gpio_direction_*(). However, note that not all platforms can read the value of output pins; those that can't should always return zero. Also, using these calls for GPIOs that can't safely be accessed without sleeping (see below) is an error.

Platform-specific implementations are encouraged to optimize the two calls to access the GPIO value in cases where the GPIO number (and for output, value) are constant. ...
--- excerpt ---

include/asm-mips/ar7/gpio.h line 63

Quoted 2 lines
include/asm-mips/ar7/gpio.h new file +2 -0
+
+	return ((readl(gpio_in) & (1 << gpio)) != 0);

The gpio API defines any non-zero value (not only '1') for "high", so "!= 0" is not required.

include/asm-mips/ar7/gpio.h line 70

Quoted 7 lines
include/asm-mips/ar7/gpio.h new file +7 -0
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	void __iomem *gpio_out =
+		(void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
+	volatile unsigned tmp;

This 'volatile' has no sense and can be just dropped.

include/asm-mips/ar7/gpio.h line 73

Quoted 3 lines
include/asm-mips/ar7/gpio.h new file +3 -0
+
+	if (gpio >= AR7_GPIO_MAX)
+		return;

Ditto.

include/asm-mips/ar7/gpio.h line 79

Quoted 6 lines
include/asm-mips/ar7/gpio.h new file +6 -0
+
+	tmp = readl(gpio_out) & ~(1 << gpio);
+	if (value)
+		tmp |= 1 << gpio;
+	writel(tmp, gpio_out);
+}

---
Atsushi Nemoto

#4 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

In reply to Matteo Croce

Partition map support

drivers/mtd/Kconfig +6 -0
index fbec8cd..c1b2508 100644
@@ -150,6 +150,12 @@ config MTD_AFS_PARTS
 	  for your particular device. It won't happen automatically. The
 	  'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
 
+config MTD_AR7_PARTS
+	tristate "TI AR7 partitioning support"
+	depends on MTD_PARTITIONS
+	---help---
+	  TI AR7 partitioning support
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
drivers/mtd/Makefile +1 -0
index 6d958a4..8451c64 100644
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
+obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
drivers/mtd/ar7part.c new file +142 -0

142 lines not on this page · raw message

#5 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

Quoted 58 lines · Matteo Croce
drivers/mtd/Kconfig +6 -0
index fbec8cd..c1b2508 100644
@@ -150,6 +150,12 @@ config MTD_AFS_PARTS
 	  for your particular device. It won't happen automatically. The
 	  'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
 
+config MTD_AR7_PARTS
+	tristate "TI AR7 partitioning support"
+	depends on MTD_PARTITIONS
+	---help---
+	  TI AR7 partitioning support
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
drivers/mtd/Makefile +1 -0
index 6d958a4..8451c64 100644
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
+obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
drivers/mtd/ar7part.c new file +19 -0
new file mode 100644
index 0000000..775041d
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2007 Eugene Konev <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * TI AR7 flash partition table.
+ * Based on ar7 map by Felix Fietkau <[email protected]>

drivers/mtd/ar7part.c line 29

Quoted 10 lines
drivers/mtd/ar7part.c new file +10 -0
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/bootmem.h>
+#include <linux/squashfs_fs.h>

There is no such header file so this won't build ...

Quoted 25 lines
drivers/mtd/ar7part.c new file +25 -0
+struct ar7_bin_rec {
+	unsigned int checksum;
+	unsigned int length;
+	unsigned int address;
+};
+
+static struct mtd_partition ar7_parts[5];
+
+static int create_mtd_partitions(struct mtd_info *master,
+				 struct mtd_partition **pparts,
+				 unsigned long origin)
+{
+	struct ar7_bin_rec header;
+	unsigned int offset, len;
+	unsigned int pre_size = master->erasesize, post_size = 0;
+	unsigned int root_offset = 0xe0000;
+
+	int retries = 10;
+
+	printk(KERN_INFO "Parsing AR7 partition map...\n");
+
+	ar7_parts[0].name = "loader";
+	ar7_parts[0].offset = 0;
+	ar7_parts[0].size = master->erasesize;
+	ar7_parts[0].mask_flags = MTD_WRITEABLE;

drivers/mtd/ar7part.c line 65

Quoted 10 lines
drivers/mtd/ar7part.c new file +10 -0
+
+	ar7_parts[1].name = "config";
+	ar7_parts[1].offset = 0;
+	ar7_parts[1].size = master->erasesize;
+	ar7_parts[1].mask_flags = 0;
+
+	do { /* Try 10 blocks starting from master->erasesize */
+		offset = pre_size;
+		master->read(master, offset,
+			sizeof(header), &len, (u_char *)&header);

The u_char type is deprecated. Use u8 from <linux/types.h> or unsigned char instead.

Quoted 67 lines
drivers/mtd/ar7part.c new file +67 -0
+		if (!strncmp((char *)&header, "TIENV0.8", 8))
+			ar7_parts[1].offset = pre_size;
+		if (header.checksum == 0xfeedfa42)
+			break;
+		if (header.checksum == 0xfeed1281)
+			break;
+		pre_size += master->erasesize;
+	} while (retries--);
+
+	pre_size = offset;
+
+	if (!ar7_parts[1].offset) {
+		ar7_parts[1].offset = master->size - master->erasesize;
+		post_size = master->erasesize;
+	}
+
+	switch (header.checksum) {
+	case 0xfeedfa42:
+		while (header.length) {
+			offset += sizeof(header) + header.length;
+			master->read(master, offset, sizeof(header),
+				     &len, (u_char *)&header);
+		}
+		root_offset = offset + sizeof(header) + 4;
+		break;
+	case 0xfeed1281:
+		while (header.length) {
+			offset += sizeof(header) + header.length;
+			master->read(master, offset, sizeof(header),
+				     &len, (u_char *)&header);
+		}
+		root_offset = offset + sizeof(header) + 4 + 0xff;
+		root_offset &= ~(u32)0xff;
+		break;
+	default:
+		printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
+		break;
+	}
+
+	master->read(master, root_offset,
+		sizeof(header), &len, (u_char *)&header);
+	if (header.checksum != SQUASHFS_MAGIC) {
+		root_offset += master->erasesize - 1;
+		root_offset &= ~(master->erasesize - 1);
+	}
+
+	ar7_parts[2].name = "linux";
+	ar7_parts[2].offset = pre_size;
+	ar7_parts[2].size = master->size - pre_size - post_size;
+	ar7_parts[2].mask_flags = 0;
+
+	ar7_parts[3].name = "rootfs";
+	ar7_parts[3].offset = root_offset;
+	ar7_parts[3].size = master->size - root_offset - post_size;
+	ar7_parts[3].mask_flags = 0;
+
+	*pparts = ar7_parts;
+	return 4;
+}
+
+static struct mtd_part_parser ar7_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = create_mtd_partitions,
+	.name = "ar7part",
+};
+
+static int __init ar7_parser_init(void)

drivers/mtd/ar7part.c line 142

Quoted 10 lines
drivers/mtd/ar7part.c new file +10 -0
+{
+	return register_mtd_parser(&ar7_parser);
+}
+
+module_init(ar7_parser_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR(	"Felix Fietkau <[email protected]>, "
+		"Eugene Konev <[email protected]>");
+MODULE_DESCRIPTION("MTD partitioning for TI AR7");

Ralf

#6 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

In reply to Matteo Croce
Quoted 1 line

+#include <linux/squashfs_fs.h>

As Ralf mentioned this is not in mainline, so you can't include it. Fortunately for you including it seems to be a rather dumb idea anyway, see below for further comments.

Quoted 1 line

+static struct mtd_partition ar7_parts[5];

Can we please get a symbolic name for that 5? Then again we only seems to use 3 anyway, and create_mtd_partitions returns 4..

drivers/mtd/ar7part.c line 46

Quoted 1 line
drivers/mtd/ar7part.c new file +1 -0
+	unsigned int root_offset = 0xe0000;

Please provide a symbolic name for this one.

drivers/mtd/ar7part.c line 50

Quoted 1 line
drivers/mtd/ar7part.c new file +1 -0
+	printk(KERN_INFO "Parsing AR7 partition map...\n");

Do we really need this printk?

drivers/mtd/ar7part.c line 71

Quoted 4 lines
drivers/mtd/ar7part.c new file +4 -0
+		if (header.checksum == 0xfeedfa42)
+			break;
+		if (header.checksum == 0xfeed1281)
+			break;

These two want symbolic names, please:

enum {
	/* some comment */
	FOO_PART_MAGIC = 0xfeedfa42,	

	/* more comment */
	BAR_PART_MAGIC = 0xfeed1281,
};

drivers/mtd/ar7part.c line 91

Quoted 10 lines
drivers/mtd/ar7part.c new file +10 -0
+	switch (header.checksum) {
+	case 0xfeedfa42:
+		while (header.length) {
+			offset += sizeof(header) + header.length;
+			master->read(master, offset, sizeof(header),
+				     &len, (u_char *)&header);
+		}
+		root_offset = offset + sizeof(header) + 4;
+		break;
+	case 0xfeed1281:

Especially as you use them here again.

drivers/mtd/ar7part.c line 110

Quoted 11 lines
drivers/mtd/ar7part.c new file +11 -0
+	default:
+		printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
+		break;
+	}
+
+	master->read(master, root_offset,
+		sizeof(header), &len, (u_char *)&header);
+	if (header.checksum != SQUASHFS_MAGIC) {
+		root_offset += master->erasesize - 1;
+		root_offset &= ~(master->erasesize - 1);
+	}

And after this I'm pretty sure either of the two hex constants above is SQUASHFS_MAGIC. But not actually the magic in the squashfs superblock, but someone decided to reuse it for the partitions magic. So one of the comments for *_PART_MAGIC becomes:

	/* same as SQUASHFS_MAGIC for some odd reason.. */
#7 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

Il Thursday 20 September 2007 19:52:05 hai scritto:

Quoted 5 lines
Quoted 1 line

+#include <linux/squashfs_fs.h>

As Ralf mentioned this is not in mainline, so you can't include it. Fortunately for you including it seems to be a rather dumb idea anyway, see below for further comments.

You're right, i'll move the magic into linux/magic.h

Quoted 4 lines
Quoted 1 line

+static struct mtd_partition ar7_parts[5];

Can we please get a symbolic name for that 5? Then again we only seems to use 3 anyway, and create_mtd_partitions returns 4..

we use 4, and bootloader is right, it returns 4 The fourth partition is empty, the kernel formats it as jffs2 when mounting

Quoted 3 lines

drivers/mtd/ar7part.c line 46

Quoted 1 line
drivers/mtd/ar7part.c new file +1 -0
+	unsigned int root_offset = 0xe0000;

Please provide a symbolic name for this one.

Ok

Quoted 3 lines

drivers/mtd/ar7part.c line 50

Quoted 1 line
drivers/mtd/ar7part.c new file +1 -0
+	printk(KERN_INFO "Parsing AR7 partition map...\n");

Do we really need this printk?

No?

Quoted 15 lines

drivers/mtd/ar7part.c line 71

Quoted 4 lines
drivers/mtd/ar7part.c new file +4 -0
+		if (header.checksum == 0xfeedfa42)
+			break;
+		if (header.checksum == 0xfeed1281)
+			break;

These two want symbolic names, please:

enum {
	/* some comment */
	FOO_PART_MAGIC = 0xfeedfa42,	

	/* more comment */
	BAR_PART_MAGIC = 0xfeed1281,
};
Quoted 12 lines

drivers/mtd/ar7part.c line 91

Quoted 10 lines
drivers/mtd/ar7part.c new file +10 -0
+	switch (header.checksum) {
+	case 0xfeedfa42:
+		while (header.length) {
+			offset += sizeof(header) + header.length;
+			master->read(master, offset, sizeof(header),
+				     &len, (u_char *)&header);
+		}
+		root_offset = offset + sizeof(header) + 4;
+		break;
+	case 0xfeed1281:

Especially as you use them here again.

Right, will do

Quoted 17 lines

drivers/mtd/ar7part.c line 110

Quoted 11 lines
drivers/mtd/ar7part.c new file +11 -0
+	default:
+		printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
+		break;
+	}
+
+	master->read(master, root_offset,
+		sizeof(header), &len, (u_char *)&header);
+	if (header.checksum != SQUASHFS_MAGIC) {
+		root_offset += master->erasesize - 1;
+		root_offset &= ~(master->erasesize - 1);
+	}

And after this I'm pretty sure either of the two hex constants above is SQUASHFS_MAGIC. But not actually the magic in the squashfs superblock, but someone decided to reuse it for the partitions magic. So one of the comments for *_PART_MAGIC becomes:

Quoted 1 line
	/* same as SQUASHFS_MAGIC for some odd reason.. */

No. There are MIPS instructions. We look for the loader start offset since it is in the first partition

#8 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

Partition map support, fixed

drivers/mtd/Kconfig +6 -0
index fbec8cd..c1b2508 100644
@@ -150,6 +150,12 @@ config MTD_AFS_PARTS
 	  for your particular device. It won't happen automatically. The
 	  'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
 
+config MTD_AR7_PARTS
+	tristate "TI AR7 partitioning support"
+	depends on MTD_PARTITIONS
+	---help---
+	  TI AR7 partitioning support
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
drivers/mtd/Makefile +1 -0
index 6d958a4..8451c64 100644
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
+obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
drivers/mtd/ar7part.c new file +151 -0

151 lines not on this page · raw message

#9 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

drivers/mtd/ar7part.c line 40

Quoted 7 lines · Matteo Croce
drivers/mtd/ar7part.c new file +7 -0
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define LOADER_MAGIC1	0xfeedfa42
+#define LOADER_MAGIC2	0xfeed1281
+#else
+#define LOADER_MAGIC1	0x42faedfe
+#define LOADER_MAGIC2	0x8112edfe
+#endif

Please keep only one defintion and use le/be32_to_cpu on it.

drivers/mtd/ar7part.c line 46

Quoted 5 lines
drivers/mtd/ar7part.c new file +5 -0
+struct ar7_bin_rec {
+	unsigned int checksum;
+	unsigned int length;
+	unsigned int address;
+};

Wich means you'd need an endianess annotation here. What about the length and address fields, are they always native-endian unlike the checksum field or will the need to be byte-swapped aswell?

#10 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

Quoted 11 lines · Christoph Hellwig

drivers/mtd/ar7part.c line 40

Quoted 7 lines · Matteo Croce
drivers/mtd/ar7part.c new file +7 -0
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define LOADER_MAGIC1	0xfeedfa42
+#define LOADER_MAGIC2	0xfeed1281
+#else
+#define LOADER_MAGIC1	0x42faedfe
+#define LOADER_MAGIC2	0x8112edfe
+#endif

Please keep only one defintion and use le/be32_to_cpu on it.

Quoted 9 lines

drivers/mtd/ar7part.c line 46

Quoted 5 lines
drivers/mtd/ar7part.c new file +5 -0
+struct ar7_bin_rec {
+	unsigned int checksum;
+	unsigned int length;
+	unsigned int address;
+};

Wich means you'd need an endianess annotation here. What about the length and address fields, are they always native-endian unlike the checksum field or will the need to be byte-swapped aswell?

<slightly off-topic, feel free to skip>
If this is indeed the squashfs magic, le/be32_to_cpu won't help. Squashfs can have either endianness, tries to detect the one actually used by checking either magic and sets a flag in the superblock. Afterwards every single access checks the flag and conditionally swaps fields around or not.

If squashfs had a fixed endianness, quite a lot of this logic could get removed and both source and object size would shrink. Some two years after requesting this for the first time, I'm thinking about just doing it myself. If I find a sponsor who pays me for it, I might even do it soon.
</offtopic>

I don't really understand why the squashfs magic number should be used in this code at all. It may have set a bad example, though. In general you should decide on a fixed endianness (1) and use the beXX_to_cpu macros when accessing data unless you have a very good reason to do otherwise.

1) Big endian is my preferred choice because it is easy to read in a hexdump and the opposite of my notebook. Being forced to do endian conversions during development/testing helps to find problems early.

Jörn

Signature · 2 lines
Joern's library part 13:
http://www.chip-architect.com/
#11 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

Il Thursday 20 September 2007 22:00:59 Jörn Engel ha scritto:

Quoted 43 lines · Christoph Hellwig
Quoted 11 lines · Matteo Croce

drivers/mtd/ar7part.c line 40

Quoted 7 lines
drivers/mtd/ar7part.c new file +7 -0
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define LOADER_MAGIC1	0xfeedfa42
+#define LOADER_MAGIC2	0xfeed1281
+#else
+#define LOADER_MAGIC1	0x42faedfe
+#define LOADER_MAGIC2	0x8112edfe
+#endif

Please keep only one defintion and use le/be32_to_cpu on it.

Quoted 9 lines

drivers/mtd/ar7part.c line 46

Quoted 5 lines
drivers/mtd/ar7part.c new file +5 -0
+struct ar7_bin_rec {
+	unsigned int checksum;
+	unsigned int length;
+	unsigned int address;
+};

Wich means you'd need an endianess annotation here. What about the length and address fields, are they always native-endian unlike the checksum field or will the need to be byte-swapped aswell?

<slightly off-topic, feel free to skip>
If this is indeed the squashfs magic, le/be32_to_cpu won't help. Squashfs can have either endianness, tries to detect the one actually used by checking either magic and sets a flag in the superblock. Afterwards every single access checks the flag and conditionally swaps fields around or not.

If squashfs had a fixed endianness, quite a lot of this logic could get removed and both source and object size would shrink. Some two years after requesting this for the first time, I'm thinking about just doing it myself. If I find a sponsor who pays me for it, I might even do it soon.
</offtopic>

I don't really understand why the squashfs magic number should be used in this code at all. It may have set a bad example, though. In general you should decide on a fixed endianness (1) and use the beXX_to_cpu macros when accessing data unless you have a very good reason to do otherwise.

Quoted 3 lines

1) Big endian is my preferred choice because it is easy to read in a hexdump and the opposite of my notebook. Being forced to do endian conversions during development/testing helps to find problems early.

I use little endian since 99% of AR7s are little endian. Dunno if le/be32_to_cpu does some runtime calculations. Do they?

#12 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

Quoted 3 lines · Matteo Croce

I use little endian since 99% of AR7s are little endian. Dunno if le/be32_to_cpu does some runtime calculations. Do they?

Only if they have to convert endianness. And even in that case I doubt that you will notice it in any benchmarks.

Jörn

Signature · 4 lines
The story so far:
In the beginning the Universe was created.  This has made a lot
of people very angry and been widely regarded as a bad move.
-- Douglas Adams
#13 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

In reply to Matteo Croce
Quoted 2 lines · Matteo Croce

I use little endian since 99% of AR7s are little endian. Dunno if le/be32_to_cpu does some runtime calculations. Do they?

They do runtime unless the argument is const. If you say that you cant change endianess of a given system during it's lifetime it's probably fine to ignore the endianess issue and always use host endian without any conversions. In that case you'll need to remove the ifdef aswell, though.

#14 lore raw

Re: [PATCH][MIPS][2/7] AR7: mtd partition map

In reply to Matteo Croce

drivers/mtd/ar7part.c line 53

Quoted 4 lines · Matteo Croce
drivers/mtd/ar7part.c new file +4 -0
+static int create_mtd_partitions(struct mtd_info *master,
+				 struct mtd_partition **pparts,
+				 unsigned long origin)
+{
    [...]

Review

Quoted 2 lines
(quoted diff) +2 -0
+		master->read(master, offset,
+			sizeof(header), &len, (u_char *)&header);
                                              ^^^^^^^^^^^

Probably we should teach mtd to use `void *' for read and write buffers, so all these ugly casts can go away...

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#15 lore raw

PATCH 3/7 AR7: gpio char device

In reply to Matteo Croce

Char device to access GPIO pins

drivers/char/Kconfig +9 -0
index b391776..b98aedf 100644
@@ -928,6 +928,15 @@ config MWAVE
 	  To compile this driver as a module, choose M here: the
 	  module will be called mwave.
 
+config AR7_GPIO
+	tristate "TI AR7 GPIO Support"
+	depends on AR7
+	help
+	  Give userspace access to the GPIO pins on the Texas Instruments AR7 
+	  processors.
+
+	  If compiled as a module, it will be called ar7_gpio.
+
 config SCx200_GPIO
 	tristate "NatSemi SCx200 GPIO Support"
 	depends on SCx200
drivers/char/Makefile +1 -0
index d68ddbe..804319e 100644
@@ -89,6 +89,7 @@ obj-$(CONFIG_COBALT_LCD)	+= lcd.o
 obj-$(CONFIG_PPDEV)		+= ppdev.o
 obj-$(CONFIG_NWBUTTON)		+= nwbutton.o
 obj-$(CONFIG_NWFLASH)		+= nwflash.o
+obj-$(CONFIG_AR7_GPIO)		+= ar7_gpio.o
 obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio.o
 obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
drivers/char/ar7_gpio.c new file +158 -0

158 lines not on this page · raw message

#16 lore raw

Re: [PATCH][MIPS][3/7] AR7: gpio char device

Quoted 4 lines · Matteo Croce

Char device to access GPIO pins

This driver is almost platform independent. The only platform-specific part is its name and AR7_GPIO_MAX. It would be great if this driver was really "generic" and could be used with any GPIO API providers.

I think there were some discussions about userspace API for GPIO on LKML, but cannot remember the detail.

David, give us a comment please?

Quoted 58 lines
drivers/char/Kconfig +9 -0
index b391776..b98aedf 100644
@@ -928,6 +928,15 @@ config MWAVE
 	  To compile this driver as a module, choose M here: the
 	  module will be called mwave.
 
+config AR7_GPIO
+	tristate "TI AR7 GPIO Support"
+	depends on AR7
+	help
+	  Give userspace access to the GPIO pins on the Texas Instruments AR7 
+	  processors.
+
+	  If compiled as a module, it will be called ar7_gpio.
+
 config SCx200_GPIO
 	tristate "NatSemi SCx200 GPIO Support"
 	depends on SCx200
drivers/char/Makefile +1 -0
index d68ddbe..804319e 100644
@@ -89,6 +89,7 @@ obj-$(CONFIG_COBALT_LCD)	+= lcd.o
 obj-$(CONFIG_PPDEV)		+= ppdev.o
 obj-$(CONFIG_NWBUTTON)		+= nwbutton.o
 obj-$(CONFIG_NWFLASH)		+= nwflash.o
+obj-$(CONFIG_AR7_GPIO)		+= ar7_gpio.o
 obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio.o
 obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
drivers/char/ar7_gpio.c new file +20 -0
new file mode 100644
index 0000000..d57a23e
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2007 Nicolas Thill <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/fs.h>

drivers/char/ar7_gpio.c line 30

Quoted 10 lines
drivers/char/ar7_gpio.c new file +10 -0
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <gpio.h>

This should be "#include <asm/gpio.h>".

Quoted 118 lines
drivers/char/ar7_gpio.c new file +118 -0
+
+#define DRVNAME "ar7_gpio"
+#define LONGNAME "TI AR7 GPIOs Driver"
+
+MODULE_AUTHOR("Nicolas Thill <[email protected]>");
+MODULE_DESCRIPTION(LONGNAME);
+MODULE_LICENSE("GPL");
+
+static int ar7_gpio_major;
+
+static ssize_t ar7_gpio_write(struct file *file, const char __user *buf,
+	size_t len, loff_t *ppos)
+{
+	int pin = iminor(file->f_dentry->d_inode);
+	size_t i;
+
+	for (i = 0; i < len; ++i) {
+		char c;
+		if (get_user(c, buf + i))
+			return -EFAULT;
+		switch (c) {
+		case '0':
+			gpio_set_value(pin, 0);
+			break;
+		case '1':
+			gpio_set_value(pin, 1);
+			break;
+		case 'd':
+		case 'D':
+			ar7_gpio_disable(pin);
+			break;
+		case 'e':
+		case 'E':
+			ar7_gpio_enable(pin);
+			break;
+		case 'i':
+		case 'I':
+		case '<':
+			gpio_direction_input(pin);
+			break;
+		case 'o':
+		case 'O':
+		case '>':
+			gpio_direction_output(pin);
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return len;
+}
+
+static ssize_t ar7_gpio_read(struct file *file, char __user *buf,
+	size_t len, loff_t *ppos)
+{
+	int pin = iminor(file->f_dentry->d_inode);
+	int value;
+
+	value = gpio_get_value(pin);
+	if (put_user(value ? '1' : '0', buf))
+		return -EFAULT;
+
+	return 1;
+}
+
+static int ar7_gpio_open(struct inode *inode, struct file *file)
+{
+	int m = iminor(inode);
+
+	if (m >= AR7_GPIO_MAX)
+		return -EINVAL;
+
+	return nonseekable_open(inode, file);
+}
+
+static int ar7_gpio_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static const struct file_operations ar7_gpio_fops = {
+	.owner   = THIS_MODULE,
+	.write   = ar7_gpio_write,
+	.read    = ar7_gpio_read,
+	.open    = ar7_gpio_open,
+	.release = ar7_gpio_release,
+	.llseek  = no_llseek,
+};
+
+static struct platform_device *ar7_gpio_device;
+
+static int __init ar7_gpio_init(void)
+{
+	int rc;
+
+	ar7_gpio_device = platform_device_alloc(DRVNAME, -1);
+	if (!ar7_gpio_device)
+		return -ENOMEM;
+
+	rc = platform_device_add(ar7_gpio_device);
+	if (rc < 0)
+		goto out_put;
+
+	rc = register_chrdev(ar7_gpio_major, DRVNAME, &ar7_gpio_fops);
+	if (rc < 0)
+		goto out_put;
+
+	ar7_gpio_major = rc;
+
+	rc = 0;
+
+	goto out;
+
+out_put:
+	platform_device_put(ar7_gpio_device);
+out:
+	return rc;

drivers/char/ar7_gpio.c line 158

Quoted 10 lines
drivers/char/ar7_gpio.c new file +10 -0
+}
+
+static void __exit ar7_gpio_exit(void)
+{
+	unregister_chrdev(ar7_gpio_major, DRVNAME);
+	platform_device_unregister(ar7_gpio_device);
+}
+
+module_init(ar7_gpio_init);
+module_exit(ar7_gpio_exit);

---
Atsushi Nemoto

#17 lore raw

Re: [PATCH][MIPS][3/7] AR7: gpio char device

Quoted 11 lines · On Sat, Sep 22 2007 at 9:50am Atsushi Nemoto <[email protected]> wrote:
Quoted 4 lines · Matteo Croce

Char device to access GPIO pins

This driver is almost platform independent. The only platform-specific part is its name and AR7_GPIO_MAX. It would be great if this driver was really "generic" and could be used with any GPIO API providers.

Quoted 4 lines

I think there were some discussions about userspace API for GPIO on LKML, but cannot remember the detail.

David, give us a comment please?

It's not yet platform-neutral even given those issues; see below. And it's insufficient by itself, which is the main technical point I'd raise: without even udev/mdev hooks, it needs manual setup.

I don't think anyone has yet *proposed* a platform-neutral userspace interface to GPIOs yet. They all seem to include at least platform specific pinmux setup ... which is probably inevitable, but that would seem to need abstracting into platform-specific hooks.

There have been a few folk expressing interest in a userspace GPIO interface, and a few system-specific examples. The most flexible ones that come to mind are on Gumstix PXA2xx boards. One enables GPIO IRQs through a gpio-events module; and a /proc/gpio/GPIOnn interface monitors all the pins and their configurations (which may mean they aren't used for GPIOs at all). On some AVR32 boards, Atmel had a (less capable) configfs interface, mostly used for LED access.

More detailed comments are embedded below.

- Dave

Quoted 11 lines

drivers/char/Kconfig config MWAVE · line 933

Quoted 11 lines
drivers/char/Kconfig +3 -0
index b391776..b98aedf 100644
@@ -928,6 +928,15 @@ config MWAVE
 	  To compile this driver as a module, choose M here: the
 	  module will be called mwave.
 
+config AR7_GPIO
+	tristate "TI AR7 GPIO Support"
+	depends on AR7

As noted, this isn't generic. It could depend on GENERIC_GPIO if the text and code were generic. I'll avoid commenting on AR7 symbols in the rest of this note; just assume that they'd all be wrong.

Quoted 51 lines
Quoted 51 lines
drivers/char/Kconfig +6 -0
+	help
+	  Give userspace access to the GPIO pins on the Texas Instruments AR7 
+	  processors.
+
+	  If compiled as a module, it will be called ar7_gpio.
+
 config SCx200_GPIO
 	tristate "NatSemi SCx200 GPIO Support"
 	depends on SCx200
drivers/char/Makefile +1 -0
index d68ddbe..804319e 100644
@@ -89,6 +89,7 @@ obj-$(CONFIG_COBALT_LCD)	+= lcd.o
 obj-$(CONFIG_PPDEV)		+= ppdev.o
 obj-$(CONFIG_NWBUTTON)		+= nwbutton.o
 obj-$(CONFIG_NWFLASH)		+= nwflash.o
+obj-$(CONFIG_AR7_GPIO)		+= ar7_gpio.o
 obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio.o
 obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
drivers/char/ar7_gpio.c new file +24 -0
new file mode 100644
index 0000000..d57a23e
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2007 Nicolas Thill <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
Quoted 8 lines

drivers/char/ar7_gpio.c line 30

Quoted 6 lines
drivers/char/ar7_gpio.c new file +6 -0
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <gpio.h>

This should be "#include <asm/gpio.h>".

Yes. The MIPS people seem to have an idiosyncratic convention whereby "-Iinclude/asm-mips/mach-XXX" and/or "-Iinclude/asm-mips" get added to the CPP flags, but relying on that is clearly nonportable.

Quoted 6 lines
Quoted 6 lines
drivers/char/ar7_gpio.c new file +6 -0
+
+#define DRVNAME "ar7_gpio"
+#define LONGNAME "TI AR7 GPIOs Driver"
+
+MODULE_AUTHOR("Nicolas Thill <[email protected]>");
+MODULE_DESCRIPTION(LONGNAME);
Quoted 8 lines

drivers/char/ar7_gpio.c line 44

Quoted 8 lines
drivers/char/ar7_gpio.c new file +8 -0
+MODULE_LICENSE("GPL");
+
+static int ar7_gpio_major;
+
+static ssize_t ar7_gpio_write(struct file *file, const char __user *buf,
+	size_t len, loff_t *ppos)
+{
+	int pin = iminor(file->f_dentry->d_inode);

The assumption here seems to be that each GPIO signal has its own device node in /dev, using a dynamically assigned major number.

Now, one problem is that puts a ceiling of 256 GPIOs on the system; and also limits their numbering scheme. Some systems already use GPIO numbers bigger than 256. Right now most systems don't have that many on-chip GPIOs, even if they use BGA-400 or similar large packages, but I'd expect that to change before long. And boards can easily have that many GPIOs (or potential ones) given I/O expanders etc.

Especially given the need to reconfigure things, I wonder if it wouldn't be better to have such stuff use configfs, with attribute operations. That could also let the GPIO names be specified to better match the system or board documentation ... e.g. vendors have several naming conventions for GPIOs (on one system, "GPIO-38"; another, "PB6"; another, "P2.6"), and sometimes board-specific names are wanted.

Quoted 5 lines
Quoted 5 lines
drivers/char/ar7_gpio.c new file +5 -0
+	size_t i;
+
+	for (i = 0; i < len; ++i) {
+		char c;
+		if (get_user(c, buf + i))
Quoted 8 lines

drivers/char/ar7_gpio.c line 57

Quoted 8 lines
drivers/char/ar7_gpio.c new file +8 -0
+			return -EFAULT;
+		switch (c) {
+		case '0':
+			gpio_set_value(pin, 0);
+			break;
+		case '1':
+			gpio_set_value(pin, 1);
+			break;

To be generic, I'd use the gpio_set_value_cansleep() variant here ... it won't hurt for built-in GPIOs, but it will be mandatory if the signal is accessed through an external I2C or SPI based GPIO expander.

Quoted 8 lines

drivers/char/ar7_gpio.c line 65

Quoted 8 lines
drivers/char/ar7_gpio.c new file +8 -0
+		case 'd':
+		case 'D':
+			ar7_gpio_disable(pin);
+			break;
+		case 'e':
+		case 'E':
+			ar7_gpio_enable(pin);
+			break;

I don't know what these ar7_gpio_{en,dis}able() calls do. Maybe they're some kind of pinmux option.

The gpio_request()/gpio_free() calls aren't used, and they should be ...

Quoted 10 lines

drivers/char/ar7_gpio.c line 74

Quoted 10 lines
drivers/char/ar7_gpio.c new file +9 -0
+		case 'i':
+		case 'I':
+		case '<':
+			gpio_direction_input(pin);
 
+			break;
+		case 'o':
+		case 'O':
+		case '>':
+			gpio_direction_output(pin);

The gpio_direction_{in,out}put() calls can fail, e.g. if the pin isn't configured as GPIO or can't work in that direction. Even AR7-specific code should check those return codes...

Quoted 13 lines
Quoted 13 lines
drivers/char/ar7_gpio.c new file +13 -0
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return len;
+}
+
+static ssize_t ar7_gpio_read(struct file *file, char __user *buf,
+	size_t len, loff_t *ppos)
+{
+	int pin = iminor(file->f_dentry->d_inode);
Quoted 8 lines

drivers/char/ar7_gpio.c line 95

Quoted 8 lines
drivers/char/ar7_gpio.c new file +8 -0
+	int value;
+
+	value = gpio_get_value(pin);
+	if (put_user(value ? '1' : '0', buf))
+		return -EFAULT;
+
+	return 1;
+}

So this is a basic GPIO facility that allows input and output GPIOs. No events reported to userspace, no pinmux.

I have nothing against basic facilities, so long as they're structured well enough that "obvious" required extensions aren't problematic.

Quoted 7 lines

drivers/char/ar7_gpio.c line 102

Quoted 7 lines
drivers/char/ar7_gpio.c new file +7 -0
+
+static int ar7_gpio_open(struct inode *inode, struct file *file)
+{
+	int m = iminor(inode);
+
+	if (m >= AR7_GPIO_MAX)
+		return -EINVAL;

This might be a reasonable place to use gpio_request(), rather than testing against an AR7-specific constant.

Quoted 7 lines

drivers/char/ar7_gpio.c line 109

Quoted 7 lines
drivers/char/ar7_gpio.c new file +7 -0
+
+	return nonseekable_open(inode, file);
+}
+
+static int ar7_gpio_release(struct inode *inode, struct file *file)
+{
+	return 0;

... and this would then be where gpio_free() is used.

Quoted 12 lines
Quoted 12 lines
drivers/char/ar7_gpio.c new file +12 -0
+}
+
+static const struct file_operations ar7_gpio_fops = {
+	.owner   = THIS_MODULE,
+	.write   = ar7_gpio_write,
+	.read    = ar7_gpio_read,
+	.open    = ar7_gpio_open,
+	.release = ar7_gpio_release,
+	.llseek  = no_llseek,
+};
+
+static struct platform_device *ar7_gpio_device;
Quoted 8 lines

drivers/char/ar7_gpio.c line 129

Quoted 8 lines
drivers/char/ar7_gpio.c new file +8 -0
+
+static int __init ar7_gpio_init(void)
+{
+	int rc;
+
+	ar7_gpio_device = platform_device_alloc(DRVNAME, -1);
+	if (!ar7_gpio_device)
+		return -ENOMEM;

Only legacy drivers should create their own device nodes. But this node doesn't seem to be used for *ANYTHING* so I don't know why it even exists...

Quoted 10 lines

drivers/char/ar7_gpio.c line 139

Quoted 10 lines
drivers/char/ar7_gpio.c new file +10 -0
+
+	rc = platform_device_add(ar7_gpio_device);
+	if (rc < 0)
+		goto out_put;
+
+	rc = register_chrdev(ar7_gpio_major, DRVNAME, &ar7_gpio_fops);
+	if (rc < 0)
+		goto out_put;
+
+	ar7_gpio_major = rc;

Similarly, there's nothing here to cause the various /dev nodes to be created by udev/mdev ... that seems like a significant omission.

If this were done with configfs, I might imagine there'd be a control node which would accept userspace commands like

- create node for GPIO N and call it "elvis"
- remove GPIO node "elvis"

The former would then gpio_request(N, "elvis") and create some configfs node called "elvis" with attributes that would let it be configured as input or output, and which would expose its value. The latter would get rid of that node and gpio_free().

Ideally, boards would be able to preload a bunch of GPIO declarations so that sysadmins didn't need to risk goofing that up.

Quoted 23 lines
Quoted 9 lines
drivers/char/ar7_gpio.c new file +9 -0
+
+	rc = 0;
+
+	goto out;
+
+out_put:
+	platform_device_put(ar7_gpio_device);
+out:
+	return rc;

drivers/char/ar7_gpio.c line 158

Quoted 10 lines
drivers/char/ar7_gpio.c new file +10 -0
+}
+
+static void __exit ar7_gpio_exit(void)
+{
+	unregister_chrdev(ar7_gpio_major, DRVNAME);
+	platform_device_unregister(ar7_gpio_device);
+}
+
+module_init(ar7_gpio_init);
+module_exit(ar7_gpio_exit);

---
Atsushi Nemoto

#18 lore raw

Re: [PATCH][MIPS][3/7] AR7: gpio char device

Quoted 14 lines · David Brownell
Quoted 4 lines

I think there were some discussions about userspace API for GPIO on LKML, but cannot remember the detail.

David, give us a comment please?

It's not yet platform-neutral even given those issues; see below. And it's insufficient by itself, which is the main technical point I'd raise: without even udev/mdev hooks, it needs manual setup.

I don't think anyone has yet *proposed* a platform-neutral userspace interface to GPIOs yet. They all seem to include at least platform specific pinmux setup ... which is probably inevitable, but that would seem to need abstracting into platform-specific hooks.

Quoted 7 lines

There have been a few folk expressing interest in a userspace GPIO interface, and a few system-specific examples. The most flexible ones that come to mind are on Gumstix PXA2xx boards. One enables GPIO IRQs through a gpio-events module; and a /proc/gpio/GPIOnn interface monitors all the pins and their configurations (which may mean they aren't used for GPIOs at all). On some AVR32 boards, Atmel had a (less capable) configfs interface, mostly used for LED access.

Thank you pointing out those issues. It seems things are much complicated than I was thinking of...

Quoted 1 line

More detailed comments are embedded below.

And these comments help us understanding how to use and implement the GPIO API. Thanks!

---
Atsushi Nemoto

#19 lore raw

PATCH 4/7 AR7: leds driver

In reply to Matteo Croce

Support for the leds in front of the board usually used to show power status, network traffic, connected eth devices etc.
Will convert it to use leds-gpio when 2.6.23 will out.

drivers/leds/Kconfig +6 -0
index 4468cb3..b1c7a32 100644
@@ -18,6 +18,12 @@ config LEDS_CLASS
 
 comment "LED drivers"
 
+config LEDS_AR7
+	tristate "LED Support for the TI AR7"
+	depends LEDS_CLASS && AR7
+	help
+	  This option enables support for the LEDs on TI AR7.
+
 config LEDS_CORGI
 	tristate "LED Support for the Sharp SL-C7x0 series"
 	depends on LEDS_CLASS && PXA_SHARP_C7xx
drivers/leds/Makefile +1 -0
index f8995c9..6d78192 100644
@@ -5,6 +5,7 @@ obj-$(CONFIG_LEDS_CLASS)		+= led-class.o
 obj-$(CONFIG_LEDS_TRIGGERS)		+= led-triggers.o
 
 # LED Platform Drivers
+obj-$(CONFIG_LEDS_AR7)			+= leds-ar7.o
 obj-$(CONFIG_LEDS_CORGI)		+= leds-corgi.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_SPITZ)		+= leds-spitz.o
drivers/leds/leds-ar7.c new file +130 -0

130 lines not on this page · raw message

#20 lore raw

Re: [PATCH][MIPS][4/7] AR7: leds driver

Quoted 3 lines · Matteo Croce

Support for the leds in front of the board usually used to show power status, network traffic, connected eth devices etc.
Will convert it to use leds-gpio when 2.6.23 will out.

Ok, I'll wait for the leds-gpio version before applying, thanks. 2.6.23 is due very soon...

Cheers,

Richard

#21 lore raw

PATCH 5/7 AR7: watchdog timer

In reply to Matteo Croce

Driver for the watchdog timer. Still doesn't reboots the machine on some boards, but we have improved and cleaned it

drivers/char/watchdog/Kconfig +6 -0
index 37bddc1..78d4940 100644
@@ -583,6 +583,12 @@ config SBC_EPX_C3_WATCHDOG
 
 # MIPS Architecture
 
+config AR7_WDT
+	tristate "TI AR7 Watchdog Timer"
+	depends on WATCHDOG && AR7
+	help
+	  Hardware driver for the TI AR7 Watchdog Timer.
+
 config INDYDOG
 	tristate "Indy/I2 Hardware Watchdog"
 	depends on SGI_IP22
drivers/char/watchdog/Makefile +1 -0
index 389f8b1..76424f2 100644
@@ -87,6 +87,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
 # M68KNOMMU Architecture
 
 # MIPS Architecture
+obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
 obj-$(CONFIG_INDYDOG) += indydog.o
 obj-$(CONFIG_WDT_MTX1)	+= mtx-1_wdt.o
 obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
drivers/char/watchdog/ar7_wdt.c new file +351 -0

351 lines not on this page · raw message

#22 lore raw

Re: [PATCH][MIPS][5/7] AR7: watchdog timer

Hi Matteo,

Sorry for the late response. Some personal/work issues prevented me in reacting faster.

drivers/char/watchdog/ar7_wdt.c line 188

Quoted 10 lines
drivers/char/watchdog/ar7_wdt.c new file +10 -0
+static int ar7_wdt_open(struct inode *inode, struct file *file)
+{
+	/* only allow one at a time */
+	if (down_trylock(&open_semaphore))
+		return -EBUSY;
+	ar7_wdt_enable_wdt();
+	expect_close = 0;
+
+	return 0;
+}

The /dev/watchdog device is a VFS (Virtual File System). We thus use a: return nonseekable_open(inode, file);

drivers/char/watchdog/ar7_wdt.c line 223

Quoted 6 lines
drivers/char/watchdog/ar7_wdt.c new file +6 -0
+static ssize_t ar7_wdt_write(struct file *file, const char *data,
+			     size_t len, loff_t *ppos)
+{
+	if (*ppos != file->f_pos)
+		return -ESPIPE;
+

Since we use the nonseekable_open we don't need the
if (*ppos != file->f_pos) return -ESPIPE;

Quoted 2 lines
(quoted diff) +2 -0
+static int __init ar7_wdt_init(void)
+{

...

Quoted 11 lines
drivers/char/watchdog/ar7_wdt.c new file +11 -0
+	rc = misc_register(&ar7_wdt_miscdev);
+	if (rc) {
+		printk(KERN_ERR DRVNAME ": unable to register misc device\n");
+		goto out_alloc;
+	}
+
+	rc = register_reboot_notifier(&ar7_wdt_notifier);
+	if (rc) {
+		printk(KERN_ERR DRVNAME
+			": unable to register reboot notifier\n");
+		goto out_register;

drivers/char/watchdog/ar7_wdt.c line 340

Quoted 10 lines
drivers/char/watchdog/ar7_wdt.c new file +10 -0
+	}
+	goto out;
+
+out_register:
+	misc_deregister(&ar7_wdt_miscdev);
+out_alloc:
+	release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
+out:
+	return rc;
+}

It's better to first register the reboot-notifier instead of registering the misc-device. The misc-device gives userspace allready access to the device and that's something that you want to do as the last action to prevent problems.

For the rest: all OK.

If you want I'll add it to the linux-2.6-watchdog-mm tree with the above mentioned changes.

Greetings,
Wim.

#23 lore raw

Re: [PATCH][MIPS][5/7] AR7: watchdog timer

Quoted 2 lines

If you want I'll add it to the linux-2.6-watchdog-mm tree with the above mentioned changes.

Yes, please
Cheers

#24 lore raw

Re: [PATCH][MIPS][5/7] AR7: watchdog timer

Hi Matteo,

Quoted 3 lines
Quoted 2 lines

If you want I'll add it to the linux-2.6-watchdog-mm tree with the above mentioned changes.

Yes, please

It's in the linux-2.6-watchdog-mm tree. I added an extra iounmap in the errorhandling of the init procedure.

Please test.

Thanks,
Wim.

#25 lore raw

PATCH 6/7 AR7: serial hack

In reply to Matteo Croce

Hack to use serial in the way the bootloader wants to.

drivers/serial/8250.c +11 -0
index f94109c..94253b7 100644
@@ -267,6 +267,13 @@ static const struct serial8250_config uart_config[] = {
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
 		.flags		= UART_CAP_FIFO,
 	},
+	[PORT_AR7] = {
+		.name		= "TI-AR7",
+		.fifo_size	= 16,
+		.tx_loadsz	= 16,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
+	},
 };
 
 #if defined (CONFIG_SERIAL_8250_AU1X00)
@@ -2453,7 +2460,11 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
 
+#ifdef CONFIG_AR7
+	wait_for_xmitr(up, BOTH_EMPTY);
+#else
 	wait_for_xmitr(up, UART_LSR_THRE);
+#endif
 	serial_out(up, UART_TX, ch);
 }
 
include/linux/serialP.h +4 -0
index e811a61..cf71de9 100644
@@ -135,6 +135,10 @@ struct rs_multiport_struct {
  * the interrupt line _up_ instead of down, so if we register the IRQ
  * while the UART is in that state, we die in an IRQ storm. */
 #define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
+#elif defined(CONFIG_AR7)
+/* This is how it is set up by bootloader... */
+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1 \
+			| UART_MCR_RTS | UART_MCR_DTR)
 #else
 #define ALPHA_KLUDGE_MCR 0
 #endif
include/linux/serial_core.h +1 -0
index 09d17b0..8ad2c3b 100644
@@ -40,6 +40,7 @@
 #define PORT_NS16550A	14
 #define PORT_XSCALE	15
 #define PORT_RM9000	16	/* PMC-Sierra RM9xxx internal UART */
+#define PORT_AR7	16
 #define PORT_MAX_8250	16	/* max port ID */
 
 /*
#26 lore raw

PATCH 7/7 AR7: ethernet

In reply to Matteo Croce

Driver for the cpmac 100M ethernet driver. Jeff, here is the meat ;)

drivers/net/Kconfig +9 -0
index 6a0863e..28ba0dc 100644
@@ -1822,6 +1822,15 @@ config SC92031
 	  To compile this driver as a module, choose M here: the module
 	  will be called sc92031.  This is recommended.
 
+config CPMAC
+	tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
+	depends on NET_ETHERNET && EXPERIMENTAL && AR7
+	select PHYLIB
+	select FIXED_PHY
+	select FIXED_MII_100_FDX
+	help
+	  TI AR7 CPMAC Ethernet support
+
 config NET_POCKET
 	bool "Pocket and portable adapters"
 	depends on PARPORT
drivers/net/Makefile +1 -0
index 9501d64..b536934 100644
@@ -157,6 +157,7 @@ obj-$(CONFIG_8139CP) += 8139cp.o
 obj-$(CONFIG_8139TOO) += 8139too.o
 obj-$(CONFIG_ZNET) += znet.o
 obj-$(CONFIG_LAN_SAA9730) += saa9730.o
+obj-$(CONFIG_CPMAC) += cpmac.o
 obj-$(CONFIG_DEPCA) += depca.o
 obj-$(CONFIG_EWRK3) += ewrk3.o
 obj-$(CONFIG_ATP) += atp.o
drivers/net/cpmac.c new file +1166 -0

1,166 lines not on this page · raw message

#27 lore raw

Re: [PATCH][MIPS][7/7] AR7: ethernet

Overall, looks pretty clean, good job!

Comments:

1) [major issue] Don't take and release a heavy lock on every single RX packet.

2) remove net_device_stats from private structure, and use net_device::stats

3) rx_ring_size should not be a module param, since that should be supported via ethtool

4) cpmac_tx_timeout() doesn't really do anything to alleviate the condition

5) don't set dev->mem_start and dev->mem_end, those are fields that are going away, and that's not their intended purpose. just store a pointer to the resource info.